Spring Boot与Angular间CORS及CSRF启用问题排查
看起来你已经做了大部分正确的配置,但跨域场景下的CSRF确实有几个容易踩坑的点,我来帮你逐一排查:
1. 修正CORS配置,允许携带Credentials
你的Spring Boot CORS配置目前只开放了路径,但跨域下要传递Cookie(包括XSRF-TOKEN),必须显式允许Credentials,并且不能用*作为允许的Origin(浏览器不允许这种组合):
@Bean public WebMvcConfigurer webMvcConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:4200") // 指定你的Angular前端地址 .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true); // 关键配置:允许请求携带Cookie } }; }
2. 确保Angular请求携带Credentials
即使后端允许了,前端请求也需要明确带上withCredentials标记,修改你的Interceptor:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const token = this.tokenExtractor.getToken(); // 先克隆请求并开启withCredentials let modifiedReq = req.clone({ withCredentials: true }); if (token) { modifiedReq = modifiedReq.clone({ setHeaders: { 'X-XSRF-TOKEN': token } }); } return next.handle(modifiedReq); }
3. 显式配置Angular的HttpClientXsrfModule
虽然默认配置应该匹配Spring Boot的命名,但显式配置可以避免潜在的命名不一致问题,在你的AppModule里调整:
import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http'; @NgModule({ imports: [ HttpClientModule, HttpClientXsrfModule.withOptions({ cookieName: 'XSRF-TOKEN', // 和Spring Boot默认的Cookie名称一致 headerName: 'X-XSRF-TOKEN' // 匹配后端预期接收的Header名称 }) ] }) export class AppModule { }
4. 检查Cookie的SameSite属性
Spring Boot的CookieCsrfTokenRepository默认SameSite是Lax,在本地跨域(不同端口)场景下,可能导致浏览器拒绝读取Cookie。你可以修改Spring Boot的CSRF配置,显式设置SameSite策略:
import org.springframework.web.util.SameSiteCookieHttpServletResponseWrapper.SameSitePolicy; @Override protected void configure(HttpSecurity http) throws Exception { CookieCsrfTokenRepository csrfRepo = CookieCsrfTokenRepository.withHttpOnlyFalse(); csrfRepo.setCookieSameSite(SameSitePolicy.LAX); // 本地HTTP环境下推荐用LAX(None需要配合Secure标记,HTTP不支持) http .cors() .and() .csrf().csrfTokenRepository(csrfRepo) // ... 其余配置 }
5. 确保先触发Cookie设置请求
XSRF-TOKEN是后端在第一次请求(通常是GET请求)时写入Cookie的,如果你的前端一开始就发送POST/PUT等需要CSRF校验的请求,可能此时Cookie还未被浏览器存储。建议在应用初始化时先发送一个简单的GET请求(比如请求健康检查接口或静态资源),确保Cookie被正确写入。
6. 检查浏览器Cookie设置
确认你的浏览器没有禁用第三方Cookie,或者将localhost加入了Cookie允许列表。比如在Chrome中,可以在设置里找到「隐私和安全」→「Cookie和其他网站数据」,确保「阻止第三方Cookie」未开启,或者添加localhost为例外。
按照这些步骤调整后,应该就能让Angular正确读取到XSRF-TOKEN Cookie了。
内容的提问来源于stack exchange,提问作者justanoob

