介绍
跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对 JavaScript 实施的安全限制
同源策略限制了如下行为:
- Cookie、LocalStorage 和 IndexDB 无法读取
- DOM 和 JS 对象无法获取
- Ajax 请求发送不出去
问题背景
在本地开发时,接口地址一般为 127.0.0.1:8000
1 | $php artisan serve |
而前端地址看个人配置,我的如下:
1 | const port = process.env.port || process.env.npm_config_port || 9528 // dev port |
1 | $ npm run dev |
这个时候直接配置接口地址来联调时就会出现跨域问题:
Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/member/company/update' from origin 'http://localhost:9528' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://localhost:9527' that is not equal to the supplied origin.
后端方案
本来准备自己写个中间件的,但是发现用的 Laravel8 默认引入了一个包 laravel-cors:
1 | "require": { |
并且已经给你生成了一个配置文件,内容非常好理解,需要设置的头都给你做好了:
1 | return [ |
把前端地址加进去后就完事了
前端方案
如果是纯前端解决跨域问题,可以用 webpack 的 devServer.proxy
1 | proxy: { |
生产环境就要 Nginx 反向代理,上文中已经给过配置:
1 | # 前端 |
不是所有的跨域情况下的请求都需要先发送一个 options 请求的。比如一些简单请求是不需要的比如 get 请求,但也不是所有的 get 请求都不会发 options
它的 Content-Type 的值仅限于下列三者之一:
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
并且没有设置如下的 自定义 Header
- Accept
- Accept-Language
- Content-Language
- Content-Type (需要注意额外的限制)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
而且还要注意一点,也不是只有 XMLHttpRequest 或者 fetch 请求才会有跨域问题,使用 drawImage 的 Canvas、Web 字体 、CSSDOM 也都是有这问题的
想了解更多可以阅读 MDN 跨源资源共享(CORS)
