如何进一步停止处理请求?

How to stop processing request any further?

如果请求中不存在某个 header,我需要阻止所有请求处理。因此,我有以下 SecurityConfig 代码,我在其中配置了一个先于其他所有内容执行的过滤器:

protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    
    httpSecurity.addFilterBefore(
        new OncePerRequestFilter() {
            @Override
            protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
                    throws ServletException, IOException {    
                if(testmode) {
                    String testModeHeader = request.getHeader("TestMode");
                    System.out.println("In testmode :"+request.getRequestURI()+" "+testModeHeader);

                    if(!testmodeHeaderValue.equals(testModeHeader)) {
                        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
                        response.flushBuffer();
                        return;
                    }
                }
                chain.doFilter(request, response);
            }
        }
        , SecurityContextPersistenceFilter.class);
    
    httpSecurity.csrf().disable()
        .authorizeRequests().antMatchers("/oauth/**", "/oauth2/**").permitAll()
        .anyRequest().authenticated()
        .and()
        .oauth2Login()
        .userInfoEndpoint()
            .userService(oauthUserService)
        .and()
        .successHandler(new AuthenticationSuccessHandler() {
            
            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, 
                    Authentication authentication) throws IOException, ServletException {
                ...code not shown...
            }
        })
        .and()
        .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

尽管发送错误代码并使用 flushBuffer 提交响应,但似乎 spring 引导仍将用户重定向到登录页面,如下输出所示:

In testmode :/token null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null
In testmode :/oauth2/authorization/google null

我需要做什么才能在不通过任何其他过滤器的情况下提交响应?

当我只向 /token 发出一个请求时,我不确定为什么会收到这么多对 /oauth2/authorization/google 的请求?

您看到的行为是尝试呈现默认错误视图 (/error) 与 Spring 安全所采用的 secure by default principle(参见示例 86)相结合。

由于您在响应中返回 401 状态代码,/error 视图在内部被调用,这导致第二次通过过滤器链。由于您的过滤器扩展了 OncePerRequestFilter,因此不会在第二次调用它,使其看起来像是被跳过了。

随后,Spring 安全过滤器链的其余部分启动,检测到对 /error 视图的未授权访问,并重定向到 /login,或者在您的情况下,因为您're using an oauth2 dependency, /oauth2/authorization/google 页面。然后循环无限继续下去。

在这种情况下,一个简单的解决方法是通过 .mvcMatchers("/error").permitAll() 或类似方式公开错误页面。值得考虑的是这是否有意义,或者这样做是否会暴露敏感信息。您可能希望使用另一种技术来处理某些错误,例如 Spring Boot.

中的 ErrorViewResolver interface