Laravel 解决 ajax 跨域问题 2 - 带头(Authorization)跨域
之前整理过 Laravel 通过中间件解决 ajax 跨域问题 教程,但最近开发一个公众号领红包的小功能依然翻了车。
当前的允许跨域中间件
AccessControlAllowOrigin.php
之前的版本里允许所有域名访问,明显不安全,这次增加了 Origin
头部来源域名判断。其他增加的部分属于景上添花,header
设置主要关键点还是在 headers
和 methods
部分。
回到问题本身,经测试普通的接口在添加了跨域头 cors
(别称)后是可以访问了,但携带了 Authorization
头部的接口浏览器会有两次请求,一次是 options
预检请求,另一次是正式请求。因为需要验证身份,所以还使用了 api
中间件,路由定义如下:
结果就是 options
401 未通过 api
(中间调试多次,也出现过 options
请求过了,但正式请求没过,显示跨域的情况)。并且 options
请求响应头部也没有携带设置的参数,从日志显示分析请求并没有经过 cors
中间件。
这就很奇怪,明明 cors
中间件在前,api
在后。对比两个中间件发现了问题:cors
是在 $next($request)
之后处理请求,而 api
是在 $next($request)
之前处理请求;cors
是后置中间件,api
是前置中间件。也就是说一个请求过来会先执行 api
中间件,再处理请求,最后执行 cors
中间件。所以这两个中间件执行顺序是固定的。
问题就出在这个固定的顺序上,options
请求是不携带参数的,它根本通过不了 api
中间件,然后返回了 401。当时并没有注意到这一点,反复调试了几天都没搞好,搞的整个人都不自信了。
确认了问题的所在,解决方法也就简单了。之前的 Laravel 通过中间件解决 ajax 跨域问题 教程里「需要注意的事项」部分也提到了这一点,我自己给忘了。那就是单独处理 options
请求,设置允许其跨域。因为有多条这样的请求,那么可以在所有的路由请求之前定义一条通用版的 options
路由:
中间注释掉的部分是另外一个老哥写的路由直接处理 options
跨域的 demo,可以在不使用路由组搭配中间件的情况下单独使用。但因为调试过程中前端报错说没有返回 200 ok 状态,就没有采纳,有兴趣的小伙伴可以单独测试看看。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。