Spring(引导)安全预身份验证,允许的资源仍然经过身份验证

问题描述:

我使用的是 Spring Boot 1.5.6(也尝试过 1.5.4).我正在使用

I am using Spring Boot 1.5.6 (also have tried with 1.5.4). I am using a

RequestHeaderAuthenticationFilter 

和一个

PreAuthenticatedAuthenticationProvider 

保护我的 spring mvc web 应用程序,并允许访问控制器路径和静态资源.

to secure my spring mvc web app and also permit access to both a controller path and static resources.

在我的

RequestHeaderAuthenticationFilter

设置我想要

setExceptionIfHeaderMissing(true);

以便我知道请求中是否发送了标头变量.

so that I know if the header variable has been sent in the request.

当我尝试访问任何允许的资源时,Spring Security 总是在请求中查找标头变量并抛出一个

When I try to access any of the permitted resources, Spring Security always looks for the header variable in the request and throws a

PreAuthenticatedCredentialsNotFoundException

为什么即使我试图访问允许的(不受保护的)资源,spring security 仍然试图查找预先验证的主体?我该如何规避这种行为?

Why is spring security still trying to look up the preauthenticated principal even though I am trying to access a permitted (non-protected) resource? How can I circumvent this behaviour?

我的 WebSecurityConfigurerAdapter 的 java 配置如下

My java config for WebSecurityConfigurerAdapter is below

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{


private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class);


@Autowired
protected UserDetailsService userDetailsService; 



@Bean
public PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider(){

    log.info("Configuring pre authentication provider");

    UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken> wrapper = 
            new UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken>(
                    userDetailsService);

    PreAuthenticatedAuthenticationProvider it = new PreAuthenticatedAuthenticationProvider();
    it.setPreAuthenticatedUserDetailsService(wrapper);

    return it;      
} 

@Bean
public RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter() throws Exception{

    RequestHeaderAuthenticationFilter it = new RequestHeaderAuthenticationFilter();
    it.setAuthenticationManager(authenticationManager());
    it.setExceptionIfHeaderMissing(true);
    return it;
}

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    log.info("configure authentication provider");
    auth.authenticationProvider(preAuthenticatedAuthenticationProvider());

}


@Override
protected void configure(HttpSecurity http) throws Exception {
    log.info("Configure HttpSecurity");
    http
        .authorizeRequests()
            .antMatchers("/permitted/**", "/css/**", "/js/**", "/images/**", "/webjars/**")
                .permitAll()
            .anyRequest()
                    .authenticated()
            .and().addFilter(requestHeaderAuthenticationFilter())

    ;
}    


 @Override
 public void configure(WebSecurity web) throws Exception {
     web
        .ignoring()
            .antMatchers("/permitted/**", "/css/**", "/js/**", "/images/**", "/webjars/**"); 
}   
}

我遇到了同样的问题,结果证明除了在 SecurityFilterChain 中注册之外,Spring Boot 还注册了 RequestHeaderAuthenticationFilter 与Servlet 上下文.解决方案是使用 FilterRegistrationBean 来防止 Boot 自动向 Servlet 上下文注册过滤器.

I had the same problem and it turned out it was related to the fact that in addition to being registered in the SecurityFilterChain, Spring Boot was also registering the RequestHeaderAuthenticationFilter with the Servlet Context. The solution is to use a FilterRegistrationBean to prevent Boot from auto registering the filter with the Servlet Context.

更多细节在这里:具有匿名访问权限的 Spring Boot 安全预身份验证方案