Spring Security没有创建CSRF令牌

问题描述 投票:1回答:1

我希望使用Spring Security(版本5.1.2)为我的Angular 7应用程序生成CSRF令牌。我在SecurityConfig文件中有以下内容:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and()
            .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}

在我的控制器中使用以下RequestMapping:

@RestController
@RequestMapping("/authentication")
public class AuthenticationController {

    @GetMapping("/csrf")
    public void getCsrfToken(){...}

    @PostMapping("/register")
    public RegisterOutputDTO register(@RequestBody UserDTO input){...}
}

我从各种渠道收集到csrfTokenRepository将在我的第一次XSRF-token调用(这是GET的用途)中自动生成带有标题/authentication/csrf的cookie,但我没有从服务器返回cookie。因此,在我的下一次POST通话中,我收到了403响应。我可能会错过什么?

This is my output

java angular spring-security csrf
1个回答
0
投票

如我对问题的评论所示,我找到了问题的答案。 Cookie不能跨域发送。

我的前端部署在localhost:3000和我的后端localhost:9080,显然被认为是不同的域。如果我去localhost:9080(我得到一个白页,但这没关系)然后我转到Chrome中的应用程序选项卡,我发现我正在寻找的XSRF cookie就像我一直期待的那样存储。这个cookie可以从我从我的前端执行的GET调用中获得。问题是cookie需要可用于localhost:3000,以便Angular可以使用cookie。

您可以通过多种方式在本地环境中解决此问题。

Use a proxy

您可以使用代理将某些URL路径映射到后端。这是我采用的解决方案。

我使用webpack dev服务器运行我的Angular应用程序。 Webpack提供了一种简单的方法来将某些URL代理到您的后端。例如:

devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 3000,
    proxy: {
        '/api': 'http://localhost:9080'
    }
}

Angular应用程序在localhost:3000上运行。任何对localhost:3000/api/*的调用。将被转发给localhost:9080/api/*。所以在我的情况下,我不再对GET执行localhost:9080/api/authentication/csrf调用,但我调用localhost:3000/api/authentication/csrf,然后将其转发到我的后端。 (我把/api添加到我的休息控制器的路径中,对于那些想知道的人。)

Deploy both applications on the same port

使用frontend-maven-plugin,您可以构建其dist文件夹的前端,然后让maven打包dist文件夹以及后端进行部署。我没有试过这个,但有各种资源表明这应该很容易用Spring启动。因此,例如,可以通过localhost:9080获得前端和后端。

Use Spring Profile to disable csrf locally

您可以使用Spring @Profile注释为本地环境和其他(测试,验收,生产)创建不同的配置。可以简单地禁用Csrf进行开发。我不喜欢这个选项,因为我喜欢尽可能保持DEV和其他环境相同。它也不是问题陈述的真正答案。

Special thanks to the answer of user @dspies which helped me find the problem.

© www.soinside.com 2019 - 2024. All rights reserved.