我正在使用Spring-Security 3.2.4和Spring Boot 1.1.0(以及相关的依赖版本4.X)。我正在编写一个将在嵌入式tomcat中运行的Web应用程序。
我正在尝试添加两个额外的过滤器(与Spring安全无关),其中一个将在Spring-Security-FilterChainProxy之前调用,另一个将在Spring-Security-FilterChainProxy之后调用。
我的Spring-Security配置文件:
@Configuration
@EnableWebMvcSecurity
public class SecurityCtxConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("pass").roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.usernameParameter("user").passwordParameter("password");
}
}
和Main类(Application.class):
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {
@Bean
RequestFilter beforeSpringSecurityFilter(){
return new RequestFilter();
}
@Bean
RequestFilter afterSpringSecurityFilter(){
return new RequestFilter();
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
和Filter实现:
public class RequestFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(request, response);
}
}
有没有办法在考虑FilterChainProxy时控制调用顺序(由WebSecurityConfigurerAdapter创建?要成为percise,所需的顺序是:
谢谢
Spring Security使用的FilterChainProxy
不是Ordered
(如果您可以订购所有过滤器)。但你应该能够在FilterRegistrationBean
中注册它,这是Ordered
并以同样的方式注册你的其他过滤器。对于安全过滤器,您可以按名称将其注入注册bean。你可以通过调用@Bean
方法注入的其他人。
同意Dave Syer所述的所有内容;)但希望添加使用FilterRegistrationBean的Java Config示例。
在我的情况下,我发现我的自定义安全过滤器(使用Spring Security)每次请求都被触发两次。添加FilterRegistrationBean
配置修复此问题。
@Bean(name = "myFilter")
public MyAuthenticationFilter myAuthenticationFilter(final MyAuthenticationEntryPoint entryPoint) {
final MyAuthenticationFilter filter = new MyAuthenticationFilter();
filter.setEntryPoint(entryPoint);
return filter;
}
/**
* We do this to ensure our Filter is only loaded once into Application Context
*
*/
@Bean(name = "authenticationFilterRegistration")
public FilterRegistrationBean myAuthenticationFilterRegistration(final MyAuthenticationFilter filter) {
final FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(filter);
filterRegistrationBean.setEnabled(false);
return filterRegistrationBean;
}
(关于我在应用程序上下文中两次注册过滤器的具体问题 - 我没有使用FilterRegistrationBean
,我也发现重新实现MyAuthenticationFilter
继承OncePerRequestFilter
而不是GenericFilterBean
也有效。但是,OncePerRequestFilter
支持来自Servlet 3.x以上和因为我正在编写公共库,所以可能需要Servlet 2.x的支持)
如果您使用的是web.xml方法,则可以按照以下方式操作:https://stackoverflow.com/a/11929129/1542363
如果您使用Java配置方法,则可以在WebSecurityConfigurerAdapter
中执行此操作
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(your-request-filter-1, ChannelProcessingFilter.class);
http.addFilterAfter(your-request-filter-2, SwitchUserFilter.class);
}
始终检查您正在使用的库版本,并参阅特定文档以了解过滤器链的正确顺序:
https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#ns-custom-filters
或者,如果您使用AbstractSecurityWebApplicationInitializer,您可以使用insertFilters
或appendFilters
。
public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
@Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
insertFilters(servletContext, new MultipartFilter());
}
}
更多信息您可以参考:https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#csrf-multipart