我有一个可以正常工作的春季安全性流程,设置了一些要求身份验证(通过令牌)的路径,而另一些我希望保持开放状态且无需令牌即可访问。我遇到的问题是,当请求进入没有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);
    }
}


我还尝试用HttpSecurity将忽略的路径放入permitAll(),但没有成功。

澄清度

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


在上述内容中,所有进入/example/**的请求都应通过安全链并通过我的过滤器,以确保对用户进行身份验证。进入/actuator的任何请求都不应通过安全筛选器链。 /example/**正常且按预期工作。但是/actuator不会。

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

最佳答案

在Spring Boot中,任何类型为@BeanFilter都将添加为servlet过滤器。最有可能发生的情况是,您的过滤器是作为与过滤器链完全分离的过滤器添加的。

您可以将@Bean初始化为AuthenticationTokenHeaderFilter并直接设置WebSecurityConfigurerAdapter(无论如何,您都可以),而不是将过滤器声明为AuthenticationManager。因此,您可以在过滤器中删除@Autowired批注。

07-24 09:48
查看更多