我有一个 Spring Boot (1.5.6) 应用程序正在使用“预认证 https://docs.spring.io/spring-security/site/docs/current/reference/html/preauth.html来自 Spring Security 的身份验证场景 (SiteMinder)。
我需要匿名公开执行器“健康”端点,这意味着对该端点的请求将not通过 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 端点,但没有成功。
我尝试过的事情:
配置健康端点以进行匿名访问而不是允许所有:
http
.authorizeRequests().antMatchers("/health")
.anonymous()
配置 WebSecurity 以忽略运行状况端点:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/health");
}
关闭安全功能all执行器端点(不知道,但我正在抓住救命稻草):
management.security.enabled=false
查看日志,问题似乎是 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
延伸AbstractPreAuthenticatedProcessingFilter
,框架知道在链中插入过滤器的位置,这就是为什么我不修改 addFilterBefore或添加过滤器After变体。也许我应该是?有人知道明确插入过滤器的正确位置吗? (我认为在 Spring Security 的早期版本中删除了显式指定过滤器顺序的需要)
我知道我可以配置RequestHeaderAuthenticationFilter
这样,如果标头不存在,它就不会抛出异常,但如果可能的话,我想保留它。
我发现这个帖子似乎与我的问题相似,但不幸的是那里也没有答案。spring-boot-security-pre 身份验证-with-permissed-resources-still-authenticator https://stackoverflow.com/questions/45971407/spring-boot-security-preauthentication-with-permitted-resources-still-authenti
任何帮助将不胜感激!
谢谢!