Angular发送Bearer Token时遇CORS问题:请求未携带Authorization头
我来帮你排查这个问题,这种情况我之前也碰到过,大概率是拦截器范围或者预检请求的处理逻辑没做好,咱们一步步来解决:
1. 先检查Angular拦截器的配置是否生效
首先要确认你的拦截器真的覆盖了所有请求(包括GET和OPTIONS),很多时候会不小心过滤掉某些请求类型,或者拦截器根本没注册成功。
拦截器核心代码要确保无遗漏
你的拦截器应该处理所有非登录类的请求,别漏掉GET:
@Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // 从本地存储/认证服务获取token const authToken = localStorage.getItem('authToken'); // 排除登录请求避免循环跳转,其余请求都添加Authorization头 if (authToken && !request.url.includes('/login')) { const authReq = request.clone({ setHeaders: { Authorization: `Bearer ${authToken}` }, withCredentials: true // 跨域请求时需要带凭证的话必须加这个 }); return next.handle(authReq); } return next.handle(request); } }
确认拦截器已在AppModule中注册
如果没注册,拦截器根本不会工作:
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { AuthInterceptor } from './auth.interceptor'; @NgModule({ // ...其他模块配置 providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true // 允许多个拦截器,这个参数不能忘 } ] }) export class AppModule { }
加日志验证拦截范围
在拦截器里加一行日志,看GET和OPTIONS请求是不是都经过了拦截器:
console.log(`拦截到请求:${request.method} ${request.url}`);
打开浏览器控制台,观察请求日志,如果OPTIONS请求没出现在日志里,那可能是你在请求里加了skipInterceptor的配置,得检查去掉。
2. 调整Spring Boot的CORS与Security配置
这是最容易踩坑的地方!浏览器的OPTIONS预检请求是自动发送的,后端必须允许它跳过认证,同时要明确允许Authorization请求头。
配置CORS允许必要的头和方法
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:4200") // 替换成你的Angular端口 .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("Authorization", "Content-Type") // 明确允许Authorization头 .allowCredentials(true) .maxAge(3600); // 预检请求缓存时间,减少重复请求 } }
让Spring Security放过OPTIONS请求
如果用了Spring Security,必须配置让OPTIONS请求不需要认证,否则预检请求会直接返回401:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.cors().and() .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 所有OPTIONS请求直接放行 .anyRequest().authenticated() .and() .oauth2ResourceServer().jwt(); // 替换成你实际用的认证方式,比如JWT/用户名密码 } }
3. 最后检查几个常见坑
- 确认token有效:如果本地存储的token过期或不存在,拦截器自然不会加头,这时候也会返回401,先去控制台看token是否存在。
- 不要手动排除OPTIONS请求:有些同学会在拦截器里判断
if (request.method !== 'OPTIONS')才加头,但其实后端已经配置放过OPTIONS了,即使OPTIONS没带Authorization也不会报错,反而手动排除可能导致逻辑混乱。
内容的提问来源于stack exchange,提问作者Milos Stambolija
相关产品推荐
相关产品推荐

