最近维护一个老的SpringMVC的应用,增加CAS单点登录。但是有个特殊的需求是保留系统本身的认证,根据需要可以走CAS单点登录认证,也可以走系统本身的认证。
设计的方案是根据输入的URL进行判断,是否跳过CAS的Filter还是跳过系统本来的认证Filter。
下面上代码:
POM文件:
org.jasig.cas.client cas-client-core3.5.0
web.xml
FirstFilter FirstFilter com.test.filter.FirstFilter FirstFilter /* CAS Single Sign Out Filter org.jasig.cas.client.session.SingleSignOutFilter casServerUrlPrefix http://localhost:8080/cas-server CAS Single Sign Out Filter *.html CAS Filter org.jasig.cas.client.authentication.AuthenticationFilter casServerLoginUrl http://localhost:8080/cas-server/login serverName http://localhost:8080 CAS Filter *.html CAS Validation Filter org.jasig.cas.client.validation.Cas10TicketValidationFilter casServerUrlPrefix http://localhost:8080/cas-server serverName http://localhost:8080 redirectAfterValidation true CAS Validation Filter *.html CAS HttpServletRequest Wrapper Filter org.jasig.cas.client.util.HttpServletRequestWrapperFilter CAS HttpServletRequest Wrapper Filter /* CAS Assertion Thread Local Filter org.jasig.cas.client.util.AssertionThreadLocalFilter CAS Assertion Thread Local Filter /*
关键的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);
}



