Spring Security 未创建 CSRF 令牌
Posted
技术标签:
【中文标题】Spring Security 未创建 CSRF 令牌【英文标题】:Spring Security not creating CSRF token 【发布时间】:2019-07-20 13:41:21 【问题描述】:我希望使用 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
会在我的第一次GET
调用(这是/authentication/csrf
的用途)中自动生成一个带有标题XSRF-token
的cookie,但我没有从那里得到cookie服务器。因此,在我的下一个POST
电话中,我收到了 403 响应。我可能会错过什么?
【问题讨论】:
只有在 cookieXSRF-TOKEN
丢失时才会创建它。查看请求标头以查看它是否已经存在。
@Andreas 我也想过这个,但我没有在标题中发送任何这样的标记。我可以在 Chrome 的应用程序选项卡中看到该 cookie 不存在。
我相信我已经找到了答案。似乎无法跨域发送 cookie。我的 Angular 应用程序托管在 localhost:3000 上,而我的 Java 后端托管在 localhost:9080 上。看来我的选择是以某种方式将它们部署在同一个域上或使用代理。来源:***.com/questions/48002670/…
【参考方案1】:
正如我的问题的 cmets 所示,我找到了问题的答案。 无法跨域发送cookie。
我的前端部署在localhost:3000
上,我的后端部署在localhost:9080
上,显然它们被认为是不同的域。如果我转到localhost:9080
(我得到一个白页,但这没关系)然后我转到 Chrome 中的应用程序选项卡,我发现我正在寻找的 XSRF cookie 就像我一直期待的那样存储.该 cookie 可从我从前端执行的 GET
调用中获得。问题是 cookie 需要对 localhost:3000
可用,这样 Angular 才能使用 cookie。
您可以通过多种方式在本地环境中解决此问题。
使用代理
您可以使用代理将某些 url 路径映射到您的后端。这是我采用的解决方案。
我使用 webpack 开发服务器运行我的 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/*
。所以就我而言,我不再对localhost:9080/api/authentication/csrf
执行GET
调用,而是调用localhost:3000/api/authentication/csrf
,然后将其转发到我的后端。 (对于那些想知道的人,我将 /api
添加到我的休息控制器的路径中。)
在同一个端口上部署两个应用程序
使用frontend-maven-plugin,您可以将前端构建到其 dist 文件夹,然后让 maven 将 dist 文件夹与后端一起打包以进行部署。我还没有尝试过,但是有各种资源表明这应该很容易通过 Spring boot 完成。所以前端和后端都可以通过localhost:9080
使用。
使用 Spring Profile 在本地禁用 csrf
您可以使用 Spring @Profile
注释为本地环境和其他环境(测试、验收、生产)创建不同的配置。可以简单地禁用 Csrf 以进行开发。我不喜欢这个选项,因为我喜欢尽可能保持 DEV 和其他环境相同。这也不是问题陈述的真正答案。
Special thanks to the answer of user @dspies which helped me find the problem.
【讨论】:
我在本地也有一个非常相似的设置,但是 Spring 正在发送 XSRF 令牌,而 Angular 将它发送回 Spring 就好了。我对这个答案很困惑。以上是关于Spring Security 未创建 CSRF 令牌的主要内容,如果未能解决你的问题,请参考以下文章
CSRF 令牌未正确更新(Ionic + Spring Security)
Spring Security 的 POST 响应标头中未设置 Angular 2 CSRF cookie
无法使用 Spring Security 创建 CSRF 令牌
使用带有 Spring Security 的 Vaadin 出现 403 CSRF 令牌错误