Spring security CSRF 保护和基于 JWT 的授权

问题描述 投票:0回答:1

我一直在试图找出如果我的(spring boot 3.1.x)应用程序中有一个 oauth2 授权流程,如果没有 CSRF 保护,它会多么容易受到攻击。据我所知,这种授权方法将使我的应用程序 CSRF 无懈可击。然而,我发现多次提到这种方法仍然容易受到 XSS 攻击,因此我尝试根据 Spring Security 6.0 文档在应用程序中配置 CSRF。前端是有角度的,我用的是

CookieCsrfTokenRepository.withHttpOnlyFalse();
之类的。例如,我发现在 POST 的情况下,流程正确地传入 XSRF 标头,并且一切正常。但是,我发现如果我进行邮递员呼叫并仅提供不记名令牌,事情仍然会通过。就像 XSRF 令牌被完全忽略一样。我没有找到有关此处发生情况的文档,但我的直觉告诉我,CSRF 已通过我拥有的授权流程隐式关闭。

有人知道这种方法有什么问题吗?

angular spring-boot csrf
1个回答
0
投票

有人知道这种方法有什么问题吗?

Angular 应用程序不应该是 OAuth2 客户端:OAuth2 客户端应该位于服务器上(例如,使用

spring-cloud-gateway
spring-boot-starter-oauth2-client
过滤器配置
TokenRelay=
)。这意味着 Angular 和 OAuth2 客户端之间的请求受到会话的保护,这使其容易受到 CSRF 的攻击(因此,您需要防范它)。

CSRF 可以响应更改应用程序状态的请求。 Spring Security 假定您的 HTTP 动词使用正确,并且仅检查

PUT
POST
DELETE
请求的 CSRF 令牌。因此,不要因为
GET
请求中缺少 CSRF 令牌而出现错误。

从 Spring Security 6 开始,使用

HttpOnly=false
设置 cookie 存储库已经不够了:你还必须定义一个过滤器。引用文档:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    CookieCsrfTokenRepository tokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
    CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler();
    // set the name of the attribute the CsrfToken will be populated on
    requestHandler.setCsrfRequestAttributeName("_csrf");
    http
        // ...
        .csrf((csrf) -> csrf
            .csrfTokenRepository(tokenRepository)
            .csrfTokenRequestHandler(requestHandler)
        )
        .addFilterAfter(new CsrfCookieFilter(), BasicAuthenticationFilter.class);

    return http.build();
}

private static final class CsrfCookieFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        CsrfToken csrfToken = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
        // Render the token value to a cookie by causing the deferred token to be loaded
        csrfToken.getToken();

        filterChain.doFilter(request, response);
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.