本文講一個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);
}
}複製代碼