【发布时间】:2018-09-14 05:40:38
【问题描述】:
我正在尝试定义两个不同的 bean(都扩展 AbstractPreAuthenticatedProcessingFilter):一个用于在“开发”配置文件处于活动状态时从请求中获取标头(例如 USER_ID),第二个用于从在“开发”配置文件不处于活动状态时请求标头。 (虽然从概念上讲,我真的只是想根据 bean 本身的存在以编程方式注册过滤器)目前,我什至没有尝试使用配置文件,因为我遇到了自动获取标题的问题在适当的过滤器链中注册。
应用使用 Spring-Boot 2.0.0.RELEASE,配置为使用嵌入式 Tomcat,服务被注解为 @RestController。下面是我的 SecurityConfig 类的简化版本:
@Configuration
@EnableWebSecurity(debug=true)
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public UserIdAuthenticationFilter UserIdAuthenticationFilter() throws Exception {
...
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
...
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable()
.headers().frameOptions().sameOrigin()
.and()
//.addFilter(jwtAuthenticationFilter())
//.addFilter(UserIdAuthenticationFilter())
.exceptionHandling()
.and().authorizeRequests()
.antMatchers("/", "/index.html", "/css/**", "/images/**", "/js/**").permitAll()
.anyRequest()
.authenticated()
.antMatchers("/**").permitAll()
;
}
}
如您所见,我已经定义了我的过滤器 bean,并且它们在应用于正确的链时工作......我看到的问题是 spring 似乎注册到过滤器某处,但是当我调用服务端点时,它从不调用我添加的过滤器代码。
运行应用程序的日志输出似乎表明正在定位过滤器...
2018-04-04 09:43:02.907 INFO 7717 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-04-04 09:43:02.907 INFO 7717 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-04-04 09:43:02.907 INFO 7717 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-04-04 09:43:02.908 INFO 7717 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2018-04-04 09:43:02.908 INFO 7717 --- [ost-startStop-1] .s.DelegatingFilterProxyRegistrationBean : Mapping filter: 'springSecurityFilterChain' to: [/*]
2018-04-04 09:43:02.908 INFO 7717 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpTraceFilter' to: [/*]
2018-04-04 09:43:02.908 INFO 7717 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webMvcMetricsFilter' to: [/*]
2018-04-04 09:43:02.908 INFO 7717 --- [ LOOK HERE ] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'userIdAuthenticationFilter' to: [/*]
2018-04-04 09:43:02.908 INFO 7717 --- [ LOOK HERE ] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'jwtAuthenticationFilter' to: [/*]
2018-04-04 09:43:02.909 INFO 7717 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet dispatcherServlet mapped to [/]
2018-04-04 09:43:02.922 DEBUG 7717 --- [ost-startStop-1] g.n.a.f.w.c.a.f.JwtAuthenticationFilter : Initializing filter 'jwtAuthenticationFilter'
2018-04-04 09:43:02.922 DEBUG 7717 --- [ost-startStop-1] g.n.a.f.w.c.a.f.JwtAuthenticationFilter : Filter 'jwtAuthenticationFilter' configured successfully
2018-04-04 09:43:02.922 DEBUG 7717 --- [ost-startStop-1] c.a.f.UserIdAuthenticationFilter : Initializing filter 'userIdAuthenticationFilter'
2018-04-04 09:43:02.922 DEBUG 7717 --- [ost-startStop-1] c.a.f.UserIdAuthenticationFilter : Filter 'userIdAuthenticationFilter' configured successfully
现在应用程序正在运行,当我尝试访问该服务时,我看到 spring 转储以下输出(启用调试):
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CorsFilter
LogoutFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
鉴于该输出,它向我表明安全过滤器链确实没有应用了我的过滤器。
也许更能说明问题的是,如果您注意到我的配置代码 sn-p 中有两行注释掉了(这是我在尝试使用基于配置文件的检测之前手动添加过滤器的地方)。如果我取消注释添加 JWT 过滤器的行(也就是手动注册过滤器,而不是依赖检测),一切似乎都按预期工作。查看调试输出,我现在在手动添加过滤器后调用端点时看到以下内容(注意 JwtAuthenticationFilter 现在存在于安全过滤器链中):
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CorsFilter
LogoutFilter
JwtAuthenticationFilter <-----
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
我真的要问两个问题...我显然不了解 spring-boot/spring-security 设置的各种过滤器链,那么在应用程序启动期间注册的 bean 有什么区别在正常的过滤器链中,与在 spring-security 过滤器链中注册的 bean 相比?谁能指出我做错了什么以及为什么?
注册这些“可选”bean 的正确方法是什么? (可选,因为可能不存在依赖于活动配置文件。)
谢谢!
【问题讨论】:
标签: java spring spring-boot spring-security