Spring boot 具有匿名访问的Spring Boot安全预验证方案

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

我有一个SpringBoot(1.5.6)应用程序,它使用SpringSecurity的“”身份验证方案(SiteMinder)

我需要匿名公开执行器“健康”端点,这意味着对该端点的请求将而不是通过SiteMinder,因此,HTTP请求标头中将不存在SM_用户标头

我面临的问题是,无论我如何配置“健康”端点,框架都会抛出
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