我实现了一个 CustomCsrfTokenRepository 将 csrf 令牌保存在 postgres 数据库中。
@Component
public class CustomCsrfTokenRepository implements CsrfTokenRepository {
private final JpaTokenRepository jpaTokenRepository;
public CustomCsrfTokenRepository(JpaTokenRepository jpaTokenRepository) {
this.jpaTokenRepository = jpaTokenRepository;
}
@Override
public CsrfToken generateToken(HttpServletRequest httpServletRequest) {
String uuid = UUID.randomUUID().toString();
return new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", uuid);
}
@Override
public void saveToken(CsrfToken csrfToken, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
String identifier = httpServletRequest.getHeader("X-IDENTIFIER");
Optional<Token> existingToken =
jpaTokenRepository.findTokenByIdentifier(identifier);
if (existingToken.isPresent()) {
Token token = existingToken.get();
token.setToken(csrfToken.getToken());
} else {
Token token = new Token();
token.setToken(csrfToken.getToken());
token.setIdentifier(identifier);
jpaTokenRepository.save(token);
}
}
@Override
public CsrfToken loadToken(HttpServletRequest httpServletRequest) {
String identifier = httpServletRequest.getHeader("X-IDENTIFIER");
Optional<Token> existingToken = jpaTokenRepository.findTokenByIdentifier(identifier);
if (existingToken.isPresent()) {
Token token = existingToken.get();
return new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf",
token.getToken());
}
return null;
}
}
我将应用程序配置为:
http.csrf(c -> {
c.csrfTokenRepository(customTokenRepository);
c.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler());
});
我有 2 个端点,一个是
GET
,另一个是 POST
。当我调用 GET
端点时,我的 csrf 令牌未写入数据库。
curl -k -H "X-IDENTIFIER:123456" https://localhost:8080/hello
只有当我调用post请求时,我才能获取保存在数据库中的token。
curl -k -X POST -H "X-IDENTIFIER:123456" -H "X-CSRF-TOKEN:2bc652f5-258b-4a26-b45" https://localhost:8080/hello
这看起来不对。当我调用
GET
请求时,我应该生成令牌并将其保存到数据库,如何实现正确的 csrf 保护?
Spring Security 在底层管理 csrf 令牌,因此您可以跳过编写此实现。不过,如果您无论如何都想这样做,您还应该实现 CsrfTokenRequestAttributeHandler 接口(您还没有这样做)。请参阅详细的 Spring 文档:https://docs.spring.io/spring-security/reference/servlet/exploits/csrf.html#csrf-integration-javascript-spa-configuration