我希望使用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
的cookie(这是/authentication/csrf
的目的),但是我没有从服务器取回cookie。因此,在我的下一个POST
通话中,我收到403响应。我可能会丢失什么?
答案 0 :(得分:0)
正如我对问题的评论所指出的,我找到了问题的答案。 无法跨域发送Cookie。
我的前端部署在localhost:3000
上,我的后端部署在localhost:9080
上,这显然被认为是不同的域。如果我转到localhost:9080
(我得到一个白页,但这没关系),然后转到Chrome中的“应用程序”标签,我发现我正在寻找的XSRF cookie像预期的那样存储一直。该cookie可从我从前端执行的GET
调用中获得。问题是localhost:3000
需要使用cookie,以便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/*
。因此,就我而言,我不再对GET
进行localhost:9080/api/authentication/csrf
调用,而是调用localhost:3000/api/authentication/csrf
,然后将其转发到我的后端。 (出于好奇,我将/api
添加到了我的rest控制器的路径中。)
使用frontend-maven-plugin,可以将前端构建到其dist文件夹,然后让maven将dist文件夹与后端一起打包以进行部署。我还没有尝试过,但是有很多资源表明使用Spring Boot应该很容易做到这一点。因此,例如,前端和后端都可以通过localhost:9080
获得。
您可以使用Spring @Profile
批注为本地环境和其他环境(测试,验收,生产)创建不同的配置。可以直接禁用Csrf进行开发。我不喜欢该选项,因为我希望尽可能使DEV和其他环境保持相同。这也不是问题陈述的真正答案。
Special thanks to the answer of user @dspies which helped me find the problem.