Angular跨域请求未携带授权Cookie(已配置withCredentials)
核心原因
浏览器的同源策略限制了跨域请求自动携带Cookie,只有当请求被判定为同域(或通过代理伪装成同域)时,才会自动附带Cookie。你的Postman测试正常是因为Postman不受浏览器同源策略约束,而代理模式下前端与代理服务器同域,因此能正常传递Cookie。
解决方案
1. 后端Spring Boot配置CORS允许凭证
必须明确指定允许的源(不能用*),同时开启allowCredentials:
全局CORS配置(WebMvc)
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("http://localhost:4200") // 必须指定具体源,不能用* .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) // 关键:允许携带凭证 .maxAge(3600); } }
若使用Spring Security,需额外配置
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.cors().and() // 启用CORS配置 .csrf().disable() // 本地开发可临时禁用,生产环境按需配置 .authorizeRequests() .antMatchers("/api/login").permitAll() .anyRequest().authenticated(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Arrays.asList("http://localhost:4200")); config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); config.setAllowedHeaders(Arrays.asList("*")); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/api/**", config); return source; } }
2. 前端Angular请求开启凭证携带
确保每个跨域请求都设置withCredentials: true,可通过单个请求配置或全局拦截器实现:
单个请求配置
import { HttpClient } from '@angular/common/http'; // 示例请求 this.http.get('http://localhost:8080/api/test', { withCredentials: true }) .subscribe(res => { // 处理响应 });
全局拦截器(推荐,无需每个请求单独设置)
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable() export class CredentialsInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // 克隆请求并开启凭证携带 const modifiedRequest = req.clone({ withCredentials: true }); return next.handle(modifiedRequest); } }
然后在app.module.ts中注册拦截器:
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { CredentialsInterceptor } from './credentials.interceptor'; @NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: CredentialsInterceptor, multi: true } ] }) export class AppModule { }
验证步骤
- 重启Spring Boot后端和Angular前端
- 调用
/api/login接口后,打开浏览器开发者工具→Application→Cookies,确认已存储后端设置的Cookie - 调用
/api/test接口时,查看Network→请求头,确认Cookie字段已被携带 - 检查响应头,确保存在
Access-Control-Allow-Credentials: true,且Access-Control-Allow-Origin为http://localhost:4200(而非*)
注意事项
- 禁止同时设置
allowedOrigins: "*"和allowCredentials: true,浏览器会直接拒绝这种不合规配置 - 若后端设置的Cookie为
HttpOnly,前端JS无法读取该Cookie,但不影响请求自动携带 - 确保Cookie的
Domain和Path配置正确,本地开发时Domain应为localhost,Path可设为/或/api
内容的提问来源于stack exchange,提问作者Craig Armstrong
相关产品推荐
相关产品推荐

