我有一个 Spring Boot (1.5.6) 应用程序,它使用来自 Spring Security 的“预身份验证”身份验证方案 (SiteMinder)。
我需要匿名公开执行器“健康”端点,这意味着对该端点的请求不会通过 SiteMinder,因此 SM_USER 标头不会出现在 HTTP 请求标头中。
我面临的问题是,无论我如何尝试配置“健康”端点,框架都会抛出一个错误,org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException
因为当请求未通过 SiteMinder 时,预期的标头(“SM_USER”)不存在。
这是我原来的安全配置:
@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();
}
我试图以几种不同的方式排除 /health 端点,但无济于事。
我尝试过的事情:
为匿名访问而不是 permitAll 配置健康端点:
http
.authorizeRequests().antMatchers("/health")
.anonymous()
将 WebSecurity 配置为忽略运行状况端点:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/health");
}
关闭所有执行器端点的安全性(不知道,但我正在抓住稻草):
management.security.enabled=false
查看日志,问题似乎是 RequestHeaderAuthenticationFilter 被注册为顶级过滤器,而不是现有securityFilterChain中的过滤器:
.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
extends AbstractPreAuthenticatedProcessingFilter
,框架知道在链中插入过滤器的位置,这就是为什么我不修改 addFilter Before或 addFilter After变体的原因。也许我应该是?有人知道明确插入过滤器的正确位置吗?(我认为在 Spring Security 的早期版本中删除了显式指定过滤器顺序的需要)
我知道我可以配置它,RequestHeaderAuthenticationFilter
这样如果标题不存在,它就不会抛出异常,但如果可能的话,我想保持这种状态。
我发现这个 SO 帖子似乎与我的问题相似,但不幸的是那里也没有答案。 spring-boot-security-preauthentication-with-permitted-resources-still-authenti
任何帮助将不胜感激!谢谢!