【问题标题】:Spring Security ignore path filter still executed when Authorization header present当授权标头存在时,Spring Security 忽略路径过滤器仍然执行
【发布时间】:2026-02-05 21:55:02
【问题描述】:

我设置了一个完全正常工作的 Spring 安全流程,其中一些路径需要身份验证(通过令牌),而其他路径我希望在没有令牌的情况下保持开放和可访问。我遇到的问题是,当请求进入没有Authorization 标头的那些开放路径之一时,过滤器将被忽略并生成正确的响应。但是,当存在Authorization 标头时,即使在被忽略的路径上,请求也会通过整个安全过滤器链,而理想的过程是完全跳过过滤器链。

下面是我的配置。

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers(DEFAULT_IGNORE_REQUESTS);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        authenticationTokenHeaderFilter.setAuthenticationManager(authenticationManager);
        http.authorizeRequests()
                .antMatchers("/example/**")
                    .authenticated()
            .and()
                .exceptionHandling()
                .accessDeniedHandler((request, response, accessDeniedException) -> {
                    response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
                })
                .authenticationEntryPoint(new HttpAuthenticationEntryPoint())
            .and()
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .cors()
            .and()
                .csrf().disable()
                .addFilter(authenticationTokenHeaderFilter)
                .addFilterBefore(new ExceptionTranslationFilter(
                                new Http403ForbiddenEntryPoint()),
                        authenticationTokenHeaderFilter.getClass()
                );
    }
public class AuthenticationTokenHeaderFilter extends AbstractPreAuthenticatedProcessingFilter {
    @Override
    protected Object getPreAuthenticatedPrincipal(HttpServletRequest httpServletRequest) {
        return httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION);
    }

    @Override
    protected Object getPreAuthenticatedCredentials(HttpServletRequest httpServletRequest) {
        return "N/A";
    }

    @Override
    @Autowired
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }
}

我还尝试将忽略的路径放在HttpSecuritypermitAll() 中,但没有成功。

澄清

String[] DEFAULT_IGNORE_REQUESTS = new String[]{ "/actuator" };

在上述内容中,任何发往/example/** 的请求都应通过安全链和我的过滤器,以确保用户已通过身份验证。任何发往/actuator 的请求都不应通过安全过滤器链。 /example/** 按预期正常工作。 /actuator 却没有。

当我发出没有 Authorization 标头的请求时,不会调用安全链。 当我发出 带有 Authorization 标头的请求时,将调用安全链并验证 Authorization 值(令牌)。如果令牌无效,则会在过滤器内引发自定义异常。即使抛出了错误,我也得到了来自/actuator 的预期响应,结果为 200。但是,在这种情况下,抛出的错误会被记录并生成堆栈跟踪,这是我不想要的,因为在这种情况下它不是错误。

【问题讨论】:

  • 能否添加 authenticationTokenHeaderFilter 的源代码?
  • @NatFar 添加到原始帖子。然后AuthenticationManager 管理验证Authorization 令牌是否正确,并可能引发错误,然后由我处理。我的整个问题是,我只希望在尝试访问受保护的路径时抛出这些错误。我可以通过检查AuthenticationManager 中的路径是否有效来构建一个混乱的解决方法以使其工作,但我想有一种方法可以通过让 Spring 处理它来使其工作。
  • @NTL 你叫什么网址? DEFAULT_IGNORE_REQUESTS 的值是多少?
  • 您说如果授权标头位于“被忽略的路径”上,则调用过滤器链——比如匹配 DEFAULT_IGNORE_REQUESTS 的路径,或者只是用户不必经过身份验证的另一路径?
  • @NatFar 抱歉我周末不在。更新了Clarification 标题下的原始帖子。

标签: java spring spring-security


【解决方案1】:

在 Spring Boot 中,Filter 类型的任何 @Bean 都会被添加为 servlet 过滤器。最有可能发生的情况是,您的过滤器被添加为完全独立于过滤器链的过滤器。

您可以在WebSecurityConfigurerAdapter 中初始化AuthenticationTokenHeaderFilter 并直接设置AuthenticationManager(无论如何您已经这样做了),而不是将您的过滤器声明为@Bean。所以可以去掉过滤器中的@Autowired注解。

【讨论】: