跨域问题扫盲
常见问题
简单介绍的跨域的核心概念、流程, 并不严谨, 详细准确的内容参考文末的参考资料.
对跨域不了解, 开发过程可能会有这样一些问题:
- 改了vue/react的代码, 为什么还是报跨域错误?
- postman不报错, 为什么前端调接口报跨域错误?
- 为什么有很多options请求?
- 跨域里的preflight是什么?
为什么会产生跨域
为了安全性考虑, 浏览器制定了"同源策略(same-origin policy)", 导致只能同域名请求, 不能跨域请求;
为了解决跨域请求, 浏览器制定了"跨源资源共享(CORS)", 符合这个规则就能跨域名请求, 不符合这个规则, 浏览器就会报跨域错误;
注意: 两条规则都只跟浏览器有关, 所以postman、java、curl等都不存在跨域问题;
浏览器的同源策略 - Web 安全 | MDN
跨源资源共享(CORS) - HTTP | MDN
跨域请求的流程
- 用户使用浏览器打开前端页面: GET http://front.com
- 服务端响应: 返回html、js、css等
- 浏览器执行js
- js发出了一个请求: GET http://gateway.com/self
- 浏览器检测到请求是一个跨域请求, 首先发送一个预检(preflight)请求, 询问服务器该接口是否支持跨域: OPTIONS http://gateway.com/self
- 服务器接收preflight请求, 如果允许跨域, 则在响应头中添加Access-Control-Allow-Origin、Access-Control-Allow-Methods等header
- 浏览器收到preflight的响应, 如果确认可以跨域请求, 则发出真正的请求: GET http://gateway.com/self
- 服务端接收请求, 返回数据, 响应头添加Access-Control-Allow-Origin等header
- 浏览器接收到响应, 如果符合CORS规则, 则把返回结果传递给js;
其中5-9步出现问题就会导致跨域错误, 比如: preflight的options请求返回401、返回的响应头里没有Access-Control-Allow-Origin等header、Access-Control-Allow-Origin不匹配等等
如何解决跨域报错
修改后端服务器
根据跨域请求的流程, 只要后端开启跨域支持、允许跨域就行了;
spring-boot里可以用CorsRegistry
、@CrossOrigin
、filter等方式解决;
加一层代理
后端代码是第三方开发的, 不能修改源码增加跨域配置, 怎么办?
可以在中间加一层代理, 前端先请求代理、代理再请求真实地址; 常见的方式:
- 配置和前端同域的代理: 如开发时使用
webpack-dev-server
- 配置开启了跨域的代理: 如nginx反向代理、gateway代理;
参考资料
博客:
不要再问我跨域的问题了 - SegmentFault 思否
15 张精美动图全面讲解 CORS - SegmentFault 思否