Angular调用REST API时OPTIONS请求返回401认证错误排查
这个问题其实是浏览器的CORS跨域预检机制在搞鬼!你遇到的情况非常典型——我来给你拆解清楚:
为什么Chrome直接请求/Postman没问题?
当你用Chrome地址栏直接请求或者Postman调用时,发送的是简单请求(满足CORS简单请求条件:请求方法为GET/HEAD/POST,且头信息仅包含Accept、Accept-Language、Content-Language、Content-Type(仅限text/plain、multipart/form-data、application/x-www-form-urlencoded))。这类请求不会触发OPTIONS预检,会直接携带你的Authorization头发送给后端,后端校验通过就返回正常结果。
为什么Angular应用会触发401?
Angular的HttpClient在发送非简单请求时(比如你自定义了Authorization头,或者用了PUT/DELETE等非简单方法),浏览器会自动先发一个OPTIONS预检请求,目的是询问后端:"我接下来要发的这个请求你允许吗?"。而根据CORS规范,OPTIONS预检请求默认不会携带自定义的请求头(包括你的Authorization)!
如果你的后端对所有请求(包括OPTIONS)都强制校验Authorization头,那这个预检请求自然会被判定为未授权,返回401错误。
解决办法(核心在后端配置)
你需要修改后端服务,让它对OPTIONS预检请求做特殊处理:
步骤1:允许OPTIONS请求跳过权限校验
后端要识别OPTIONS请求,直接放行,不校验Authorization头。比如:- 如果你用Spring Boot,可以在拦截器/过滤器里判断请求方法是OPTIONS时,直接返回成功响应;
- 如果你用Node.js+Express,可以用
cors中间件,它会自动处理OPTIONS预检; - 其他后端框架同理,找到全局请求拦截的地方,给OPTIONS请求开绿灯。
步骤2:返回正确的CORS响应头
处理OPTIONS请求时,必须返回以下关键头信息:Access-Control-Allow-Origin: 你的Angular应用域名(比如http://localhost:4200) Access-Control-Allow-Methods: 允许的请求方法(GET, POST, PUT, DELETE等) Access-Control-Allow-Headers: Authorization, Content-Type等你自定义的头 Access-Control-Max-Age: 3600(预检结果的缓存时间,减少重复预检)
Angular端的小检查(可选)
确保你是通过HttpInterceptor或者直接在请求里正确设置了Authorization头,比如:
// 示例:HttpInterceptor统一添加Authorization @Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const authReq = req.clone({ headers: req.headers.set('Authorization', `Bearer ${yourToken}`) }); return next.handle(authReq); } }
不过这里要注意:Angular的HttpClient默认不会给OPTIONS请求添加自定义头,这是符合CORS规范的,所以不用特意修改拦截器逻辑。
总结一下:问题出在后端对OPTIONS请求也做了权限校验,而浏览器的预检请求根本不会带Authorization头。只要后端调整一下对OPTIONS请求的处理逻辑,这个问题就能解决啦!
内容的提问来源于stack exchange,提问作者Aditya Vashishtha

