Spring boot 具有匿名访问的Spring Boot安全预验证方案
我有一个SpringBoot(1.5.6)应用程序,它使用SpringSecurity的“”身份验证方案(SiteMinder) 我需要匿名公开执行器“健康”端点,这意味着对该端点的请求将而不是通过SiteMinder,因此,HTTP请求标头中将不存在SM_用户标头 我面临的问题是,无论我如何配置“健康”端点,框架都会抛出Spring boot 具有匿名访问的Spring Boot安全预验证方案,spring-boot,spring-security,spring-boot-actuator,pre-authentication,anonymous-access,Spring Boot,Spring Security,Spring Boot Actuator,Pre Authentication,Anonymous Access,我有一个SpringBoot(1.5.6)应用程序,它使用SpringSecurity的“”身份验证方案(SiteMinder) 我需要匿名公开执行器“健康”端点,这意味着对该端点的请求将而不是通过SiteMinder,因此,HTTP请求标头中将不存在SM_用户标头 我面临的问题是,无论我如何配置“健康”端点,框架都会抛出org.springframework.security.web.authentication.preauth.preauthenticatedCredentialsFound
org.springframework.security.web.authentication.preauth.preauthenticatedCredentialsFoundException
,因为当请求未通过SiteMinder时,预期的头(“SM_用户”)不存在
这是我最初的安全配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests().antMatchers("/cars/**", "/dealers/**")
.hasAnyRole("CLIENT", "ADMIN")
.and()
.authorizeRequests().antMatchers("/health")
.permitAll()
.and()
.authorizeRequests().anyRequest().denyAll()
.and()
.addFilter(requestHeaderAuthenticationFilter())
.csrf().disable();
}
@Bean
public Filter requestHeaderAuthenticationFilter() throws Exception {
RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager());
return filter;
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(preAuthProvider());
}
@Bean
public AuthenticationProvider preAuthProvider() {
PreAuthenticatedAuthenticationProvider authManager = new PreAuthenticatedAuthenticationProvider();
authManager.setPreAuthenticatedUserDetailsService(preAuthUserDetailsService());
return authManager;
}
@Bean
public AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> preAuthUserDetailsService() {
return new UserDetailsByNameServiceWrapper<>(inMemoryUserDetails());
}
@Bean
public UserDetailsService inMemoryUserDetails() {
return new InMemoryUserDetailsManager(getUserSource().getUsers());
}
@Bean
public UserHolder getUserHolder() {
return new UserHolderSpringSecurityImple();
}
@Bean
@ConfigurationProperties
public UserSource getUserSource() {
return new UserSource();
}
将WebSecurity配置为忽略运行状况终结点:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/health");
}
关闭所有执行器端点的安全性(不知道,但我正在抓紧救命稻草):
查看日志,问题似乎是RequestHeaderAuthenticationFilter正在注册为顶级过滤器,而不是现有的安全过滤器链中的过滤器:
.s.DelegatingFilterProxyRegistrationBean : Mapping filter: 'springSecurityFilterChain' to: [/*]
o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*]
o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestHeaderAuthenticationFilter' to: [/*]
根据我的理解,由于RequestHeaderAuthenticationFilter
扩展了AbstractPreAuthenticationdProcessingFilter
,因此框架知道在链中插入过滤器的位置,这就是为什么我不在之前修改addFilter或之后修改addFilter变体的原因。也许我应该是?有人知道明确插入过滤器的正确位置吗?(我认为在以前版本的Spring Security中,不需要显式指定过滤器顺序)
我知道我可以配置RequestHeaderAuthenticationFilter
,以便在标头不存在时不会引发异常,但如果可能,我希望保持该状态
我发现这篇帖子似乎和我的问题很相似,但不幸的是也没有答案。
任何帮助都将不胜感激!
谢谢 问题实际上是RequestHeaderAuthenticationFilter被注册为顶级过滤器(不需要的)和Spring Security FilterChain内的过滤器链(需要的) “双重注册”的原因是Spring Boot将自动向Servlet容器注册任何
过滤器bean
为了防止“自动注册”,我只需定义一个FilterRegistrationBean
如下:
@Bean
public FilterRegistrationBean registration(RequestHeaderAuthenticationFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}
文件:
另一种/更简单的解决方案:
只是不要将RequestHeaderAuthenticationFilter
类标记为@Bean
,这很好,因为该特定过滤器不需要任何类型的DI。通过不将筛选器标记为@Bean
,Boot将不会尝试自动注册它,从而无需定义FilterRegistrationBean。问题实际上是RequestHeaderAuthenticationFilter被注册为顶级筛选器(不需要)以及弹簧安全过滤器链中的(需要)
“双重注册”的原因是Spring Boot将自动向Servlet容器注册任何过滤器bean
为了防止“自动注册”,我只需定义一个FilterRegistrationBean
如下:
@Bean
public FilterRegistrationBean registration(RequestHeaderAuthenticationFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}
文件:
另一种/更简单的解决方案:
只是不要将RequestHeaderAuthenticationFilter
类标记为@Bean
,这很好,因为该特定过滤器不需要任何类型的DI。通过不将筛选器标记为@Bean
,Boot将不会尝试自动注册它,从而无需定义FilterRegistrationBean。提供的答案很可能不完整,因为Sean Casey进行了太多的尝试和错误更改,以至于无法了解哪个配置实际解决了问题。我正在发布我的发现,我相信这些发现具有正确的配置:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/health");
}
如果您错误地将RequestHeaderAuthenticationFilter
注册为@Bean
,如原始答案所示,请将其删除。只需将其创建为普通实例并将其添加为过滤器即可正确注册:
@Override
protected void configure(HttpSecurity http) throws Exception {
RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
// configure your filter
http
.authorizeRequests().anyRequest().authenticated()
.and()
.addFilter(filter)
.csrf().disable();
}
Sean Casey尝试过但最初失败的神奇配置(由于身份验证过滤器的双重注册)是WebSecurity
配置:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/health");
}
请注意,添加HttpSecurity
antMatchers
在这种情况下没有任何作用,似乎WebSecurity
是一个具有优先权并控制过程的安全机制
额外:根据Spring安全文档,WebSecurity.ignore
方法应该用于静态资源,而不是动态资源,动态资源应该映射为允许所有用户。然而,在这种情况下,映射似乎被预验证过滤器覆盖,它强制使用更激进的忽略场景。提供的答案很可能不完整,因为Sean Casey进行了太多的尝试和错误更改,以至于无法了解哪个配置实际解决了问题。我正在发布我的发现,我相信这些发现具有正确的配置:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/health");
}
如果您错误地将RequestHeaderAuthenticationFilter
注册为@Bean
,如原始答案所示,请将其删除。只需将其创建为普通实例并将其添加为过滤器即可正确注册:
@Override
protected void configure(HttpSecurity http) throws Exception {
RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
// configure your filter
http
.authorizeRequests().anyRequest().authenticated()
.and()
.addFilter(filter)
.csrf().disable();
}
Sean Casey尝试过但最初失败的神奇配置(由于身份验证过滤器的双重注册)是WebSecurity
配置:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/health");
}
请注意,添加HttpSecurity
antMatchers
在这种情况下没有任何作用,似乎WebSecurity