Servlet 跳过特定的过滤器Filter

最近维护一个老的SpringMVC的应用,增加CAS单点登录。但是有个特殊的需求是保留系统本身的认证,根据需要可以走CAS单点登录认证,也可以走系统本身的认证。

设计的方案是根据输入的URL进行判断,是否跳过CAS的Filter还是跳过系统本来的认证Filter。

 

下面上代码:

POM文件:

<dependency>
    <groupId>org.jasig.cas.client</groupId>
    <artifactId>cas-client-core</artifactId>
    <version>3.5.0</version>
</dependency>

web.xml

<filter>
		<filter-name>FirstFilter</filter-name>
		<display-name>FirstFilter</display-name>
		<description></description>
		<filter-class>com.test.filter.FirstFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>FirstFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
    
    <filter>
        <filter-name>CAS Single Sign Out Filter</filter-name>
        <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>http://localhost:8080/cas-server</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CAS Single Sign Out Filter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>CAS Filter</filter-name>
        <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
        <init-param>
            <param-name>casServerLoginUrl</param-name>
            <param-value>http://localhost:8080/cas-server/login</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://localhost:8080</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CAS Filter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    
    <filter>
        <filter-name>CAS Validation Filter</filter-name>
        <filter-class>
            org.jasig.cas.client.validation.Cas10TicketValidationFilter</filter-class>
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>http://localhost:8080/cas-server</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://localhost:8080</param-value>
        </init-param>
        <init-param>
            <param-name>redirectAfterValidation</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CAS Validation Filter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
   
    <filter>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
   </filter>
   <filter-mapping>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <url-pattern>/*</url-pattern>
   </filter-mapping>
   
    <filter>
        <filter-name>CAS Assertion Thread Local Filter</filter-name>
        <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CAS Assertion Thread Local Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

关键的FirstFilter的代码:

说明:chain 有个filters的属性数组,是过滤器链,里边放的是ApplicationFilterConfig 是FilterConfig的一个实现类,ApplicationFilterConfig里有个属性叫filterDef就是过滤器定义,这个类的FilterClass和FilterName保存了过滤器类和过滤器名,这样就可以根据过滤器类或名字找到要剔除的过滤器,然后将对应的ApplicationFilterConfig 从数组里剔除就可以了。剔除不能是置为null就完了,因为它是从头往后依次执行的,如果中间有null会报错,要置null后将后边的往前移,还有就是要改chain过滤器个数属性。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    String url = ((HttpServletRequest)request).getRequestURL().toString();
    String queryString = ((HttpServletRequest)request).getQueryString();

    String[] filterStrings = {"AuthenticationFilter", "Cas10TicketValidationFilter", "HttpServletRequestWrapperFilter", "AssertionThreadLocalFilter", "SingleSignOutFilter"};

    if(queryString != null) {
        if(queryString.endsWith("111")) {
            try {
                Field field = chain.getClass().getDeclaredField("filters");
                field.setAccessible(true);
                FilterConfig[] filters = (FilterConfig[])field.get(chain);
                int k = 0;
                for (int i = 0;i< filters.length;i++) {
                    if (filters[i]!=null) {
                        Field field2 = filters[i].getClass().getDeclaredField("filterDef");
                        field2.setAccessible(true);
                        Field field3 = field2.get(filters[i]).getClass().getDeclaredField("filterClass");
                        field3.setAccessible(true);
                        String filterClass = (String)field3.get(field2.get(filters[i]));

                        for (String str1 : filterStrings) {
                            if(filterClass.endsWith(str1)) {
                                filters[i] = null;
                                k++;
                                break;
                            }
                        }

                        field3.setAccessible(false);
                        field2.setAccessible(false);
                    }
                }

                int index = 0;
                for(int i = 0; i< filters.length; i++) {
                    if (index==0 && filters[i] == null) {
                        index = i;
                    }
                    else if(index != 0 && filters[i] != null) {
                        filters[index] = filters[i];
                        filters[i] = null;
                        i = index;
                        index = 0;
                    }
                }

                field.setAccessible(false);
                Field n = chain.getClass().getDeclaredField("n");
                n.setAccessible(true);
                n.set(chain,n.getInt(chain)-k);
                n.setAccessible(false);
            }
            catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }

    chain.doFilter(request, response);
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值