axios 添加登录拦截器后出现 preflight response 错误
前言
为了加强网站安全性,给除了登录注册等特殊页面外的页面路由都加上了访问控制。然后问题就出现了,接口请求没有返回值了!抛了这样一个错误:
1 | Request header field 8080:1 Authorization is not allowed by Access-Control-Allow-Headers in preflight response |
之前的跨域设置居然不管用了!
挣扎
分析拦截器代码
看看这个拦截器代码究竟做了什么!
1 | // http request 拦截器 |
嗯!debugger一波找到原因在第五行,添加了一个新的请求头Authorization
。
1 | config.headers.Authorization = `token ${store.state.token}`; |
然而,在前端的请求中并没有看到Authorization
这个头。。
分析请求
在查看请求详情的时候发现一条重要信息:
options请求过后没有请求接口,那么就证明是服务端拒绝了访问。
跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是
GET
以外的 HTTP 请求,或者搭配某些 MIME 类型的POST
请求),浏览器必须首先使用OPTIONS
方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。— 来自 MDN web docs
填坑
解决的办法也很简单,在服务端的跨域拦截器中给OPTIONS
方法放行。
1 | // 新增一个 Authorization 请求头 |
服务端放行OPTIONS
方法后,再次请求,就可以看到同一个请求发送了两次。第一条为 options 方法,第二条请求就是 post 或 get 请求啦,并且在 header 中也可以看到 axios 拦截器设置的 Authorization 了。
参考链接