我一直在试图找出如果我的(spring boot 3.1.x)应用程序中有一个 oauth2 授权流程,如果没有 CSRF 保护,它会多么容易受到攻击。据我所知,这种授权方法将使我的应用程序 CSRF 无懈可击。然而,我发现多次提到这种方法仍然容易受到 XSS 攻击,因此我尝试根据 Spring Security 6.0 文档在应用程序中配置 CSRF。前端是有角度的,我用的是
CookieCsrfTokenRepository.withHttpOnlyFalse();
之类的。例如,我发现在 POST 的情况下,流程正确地传入 XSRF 标头,并且一切正常。但是,我发现如果我进行邮递员呼叫并仅提供不记名令牌,事情仍然会通过。就像 XSRF 令牌被完全忽略一样。我没有找到有关此处发生情况的文档,但我的直觉告诉我,CSRF 已通过我拥有的授权流程隐式关闭。
有人知道这种方法有什么问题吗?
有人知道这种方法有什么问题吗?
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);
}
}