是否可以将同站点属性添加到 Spring 安全 CSRF 的 .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())

Is it possible to add same-site attribute to Spring Security CSRF's .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())

我的安全配置有以下一行:

...csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())...

每个请求都会将 csrf cookie 发送回客户端。此 cookie 没有设置同站点属性。是否也可以添加相同的站点属性?我查看了 class 中的一些方法,据我所知没有关于额外属性的信息。

如何做到这一点?

不幸的是,从版本 4.0.1 开始,servlet-api 不允许您将 Same-Site 属性添加到 Cookie。希望这会很快改变。

但与此同时,您可以提供自己的 CsrfTokenRepository 实现,而不是向 HttpServletResponse 添加 Cookie(因此受到 servlet-api 的限制)的 cookie 表示),直接在 HTTP header:

中设置 cookie
public class CustomCsrfTokenRepository implements CsrfTokenRepository {
    // implement other methods...

    @Override
    public void saveToken(CsrfToken token, HttpServletRequest request,
            HttpServletResponse response) {

        // some version of this:
        response.setHeader("Set-Cookie", "HttpOnly; SameSite=strict");
    }
}

大家可以看一下CookieCsrfTokenRepository来填补空白。

插话并遵循 NatFars 的回答,此解决方案在 Kotlin 中特别简单,您可以委托给其他对象,而无需以 hacky 方式从原始对象复制代码:

class CookieCsrfTokenRepositoryWrapper(private val repo: CsrfTokenRepository): CsrfTokenRepository by repo {

    override fun saveToken(token: CsrfToken?, req: HttpServletRequest?, res: HttpServletResponse?) {
        repo.saveToken(token, req, res)
        res?.getHeaders("Set-Cookie")?.toList()?.forEach {
            if(it.contains("XSRF") && !it.contains("SameSite"))
                res.setHeader("Set-Cookie", "$it; SameSite=strict")
        }
    }
}

val repo = CookieCsrfTokenRepositoryWrapper(CookieCsrfTokenRepository.withHttpOnlyFalse())

关于 Kotlin 中的委托:https://kotlinlang.org/docs/reference/delegation.html