本文讲一个spring security自定义filter很是容易出现的一个问题,那就是filter被执行两遍。css
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public DemoFilter demoFilter(){
return new DemoFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(demoFilter(),AnonymousAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/login","/css/**", "/js/**","/fonts/**").permitAll()
.anyRequest().authenticated();
}
}复制代码
其中DemoFilter以下spring
public class DemoFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//do something
filterChain.doFilter(servletRequest, servletResponse);
}
}复制代码
在spring容器托管的GenericFilterBean的bean,都会自动加入到servlet的filter chain,而上面的定义,还额外把filter加入到了spring security的
AnonymousAuthenticationFilter以前。而spring security也是一系列的filter,在mvc的filter以前执行。所以在鉴权经过的状况下,就会前后各执行一次。bash
不把filter托管给spring,直接new,好比mvc
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(new DemoFilter(),AnonymousAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/login","/css/**", "/js/**","/fonts/**").permitAll()
.anyRequest().authenticated();
}
}复制代码
有时候filter须要访问spring容器的资源,托管给容器可能好些,那么这个时候,就能够像FilterSecurityInterceptor作个标记FILTER_APPLIEDide
public class DemoFilter extends GenericFilterBean {
private static final String FILTER_APPLIED = "__spring_security_demoFilter_filterApplied";
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (servletRequest.getAttribute(FILTER_APPLIED) != null) {
filterChain.doFilter(servletRequest, servletResponse);
return ;
}
//do something
servletRequest.setAttribute(FILTER_APPLIED,true);
filterChain.doFilter(servletRequest, servletResponse);
}
}复制代码