Spring Security 如何用nextjs作为fe和spring安全应用程序作为be来实现csrf

xzlaal3s  于 2023-10-20  发布在  Spring
关注(0)|答案(1)|浏览(127)

我有一个用nextjs作为前端和spring Boot 作为服务器的项目。我正在做用户登录/注册功能。主流程完成后,用户可以向后端发送登录后请求。现在这两个应用程序都在我自己的电脑上,并且使用不同的端口。CORS机构正常。如果我禁用了csrf,一切都很好。但如果我启用它,用户无法发送POST请求成功.
我试着将这段代码添加到spring安全配置中,如下所示:

http
    .csrf(csrf -> {
        CookieCsrfTokenRepository cookieCsrfTokenRepository = new CookieCsrfTokenRepository();
        cookieCsrfTokenRepository.setCookieCustomizer(cookie -> {
            cookie.sameSite("None");
            cookie.maxAge(3600L);
            cookie.httpOnly(false);
            cookie.secure(true);
            cookie.domain("localhost");
    });

在发送get请求后,我可以在浏览器调试面板中看到XSRF cookie:

在这个GET请求得到包含XSRF的cookie后,我立即发送一个带有凭据字段的POST请求。

const fetchCsrf = async () => {
        console.log("get csrf begin");
        const response = await fetch(apiEndpoint(RequestURL.csrfToken), {
            // credentials: 'include',
        });
        console.log("get csrf complete: ", await response.json());
        console.log("--- XSRF-TOKEN = ", response.headers.get("XSRF-TOKEN"));

        const response1 = await fetch("http://localhost:8081/api/auth/test", {
            method: "POST",
            credentials: "include",
        });
        console.log("response1 = ", await response1.json());
    }

据我所知,XSRF cookie应该包含在测试请求中,但实际上它没有。
我真的不知道为什么。请帮帮我

pftdvrlh

pftdvrlh1#

我把自己的问题整理好,把答案写在这里,希望能帮助到别人。
关键是当我在网站启动时请求csrf令牌时,spring security通过响应告诉我如何使用它。

@GetMapping("/csrf")
    public ResponseEntity<HTTPResponse<?>> csrfToken(HttpServletResponse response
            , CsrfToken token) {
        return ResponseEntity.ok(new HTTPResponse<>(token));
    }

向此端点发送请求,我会得到响应:

{
    "code": "0",
    "message": "success",
    "body": {
        "headerName": "X-XSRF-TOKEN",
        "token": "-KhhF6VGuc5Al4MmziymxHWx8TtcV5ARmdY84fBDTxyWX19Nm5BQdZRx2P5tp-AVqAGSpUXT3AM_NqI8qLcK2MV2di33Ojx1",
        "parameterName": "_csrf"
    }
}

在body字段中,“parameterName”告诉我是否可以将csrf令牌作为任何请求的参数发送,而“headerName”告诉我可以在任何名称为“headerName”的请求头中发送csrf。
只要spring security通过这两种方式之一接收到csrf,就可以成功验证请求。
此外,fe发送的每个post请求都需要包含credential: "include"。而spring be csrf应设置为:

.csrf(csrf -> {
                    CookieCsrfTokenRepository cookieCsrfTokenRepository = new CookieCsrfTokenRepository();
                    cookieCsrfTokenRepository.setCookieCustomizer(cookie -> {
                        cookie.sameSite("None");
                        cookie.secure(true);
                        cookie.httpOnly(false);
                    });
                    csrf.csrfTokenRepository(cookieCsrfTokenRepository);
                })

相关问题