我正在使用 spring 并通过 HttpSessionCsrfTokenRepository 启用 csrf,我清楚地知道客户端是否将 csrf 令牌作为请求的 _csrf 参数或 X-CSRF-TOKEN 标头发送,spring 拾取令牌并使用使用生成的令牌进行验证
generateToken(HttpServletRequest request)
但我的问题是 spring 在内部是如何做到这一点的。
我提出这个问题的原因是:
1.我有一个 Rest POST 调用,它获取凭据并验证 用户的身份。但是因为我想添加一个 csrf 令牌 休息呼叫作为安全层我想将其添加到帖子正文中 以防止 csrf 令牌泄漏。
因此,如果我知道 spring security 如何在内部过滤这些令牌,那将会很有帮助。我修改了 spring 文档,但这主要是我们如何在带有隐藏字段或元标记的表单中使用 CSRF 令牌以及带有标头的 Ajax 调用。
我也想听到对我的设计的任何评论,如果将令牌放在正文中是好的(我确信它不是一个简单的 url 参数来泄漏令牌),或者我应该将它放在标题中。我只是不想仅仅因为它简单就倾向于使用 header 。寻找最佳解决方案。
请透露一些信息。
如果您想研究一下,Spring 中 CsrfTokenRepository 有多种实现。例如:
IMO 将令牌保留在标题上是件好事(可能更安全?),因为我能想到的原因很少..
您无法在 GET 请求的正文上设置令牌。您希望所有端点保持一致(您今天可能不需要它,但事情变化得很快)
明天如果您想更改您的身份验证模型,您不想更改您的请求正文。当请求正文发生更改时,您就违反了与客户的合同
如果您将身份验证模型更改为授权服务器,您可以在服务之前添加代理服务器(例如ngnix?),我们将其称为身份验证代理。您可以将所有与安全相关的事情留给此身份验证代理,它会检查标头并为您进行验证。您不希望代理查看您的请求正文,您可以专注于您的业务实现
这只是我根据我的经验得出的意见。
注意:此信息适用于
Spring Security 6
,但旧版本也可能相同。
现在,让我们开始吧。
CsrfTokenRepository
接口: CookieCsrfTokenRepository
和 HttpSessionCsrfTokenRepository
CookieCsrfTokenRepository
。loadToken(HttpServletRequest request)
从请求收到的cookie中提取令牌。 (loadToken方法在RepositoryDeferredCsrfToken
类中)DefaultCsrfToken
的对象。 (new DefaultCsrfToken(this.headerName, this.parameterName, token)
)CsrfFilter
类中。requestHandler.resolveCsrfTokenValue(request, csrfToken)
方法从标头/参数中提取CSRF令牌。 (方法如下)@Override
default String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) {
Assert.notNull(request, "request cannot be null");
Assert.notNull(csrfToken, "csrfToken cannot be null");
String actualToken = request.getHeader(csrfToken.getHeaderName());
if (actualToken == null) {
actualToken = request.getParameter(csrfToken.getParameterName());
}
return actualToken;
}
403 forbidden
状态 :(