【问题标题】:How to stop processing request any further?如何进一步停止处理请求?
【发布时间】:2021-11-15 13:46:43
【问题描述】:

如果请求中不存在某个标头,我需要阻止所有请求处理。所以,我有以下 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 boot仍在将用户重定向到登录页面,如下输出所示:

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 发出这么多请求是什么?

【问题讨论】:

    标签: spring-boot spring-security spring-security-oauth2 spring-filter


    【解决方案1】:

    您看到的行为是尝试呈现默认错误视图 (/error) 以及 Spring Security 使用的 secure by default principle(参见示例 86)。

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

    随后,Spring Security 过滤器链的其余部分启动,检测到对 /error 视图的未经授权访问,并重定向到 /login,或者在您的情况下,因为您使用的是 oauth2 依赖项,/oauth2/authorization/google页。然后循环无限循环。

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

    【讨论】:

    • .mvcMatchers("/error").permitAll() 修复了它。感谢您的详细解释。
    猜你喜欢
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    相关资源
    最近更新 更多