为什么要跨域?
浏览器自带一个同源策略,即端口、主机名和协议完全一致得两个URL被称为同源。 不同源的网页,不能共享数据 这就造成了一个问题,前、后端的URL如果不相同,应该怎么共享数据呢? 三种方法:CORS,JSONP,反向代理。 它们都需要后端的参与
CORS(cross origin-resource share)
步骤
- 假设 a.com:8888 想把GET /data 共享给 b.com:7777
- /data 在响应头设置 Access-Control-Allow-Origin:b.com:7777
- 没了
复杂请求(MDN) 假设 a.com:8888 想把 POST /sign_in 共享给 b.com:7777
- a.com 后端需要响应OPTIONS请求
- a.com后端需要响应POST请求
CORS的本质
简单请求: A 通过响应头告诉浏览器,我愿意共享给 B 复杂请求:为了防止 POST/PUT/PATCH 请求对数据造成影响,浏览器会先发 OPTIONS 请求,问A接不接受 POST/PUT/PATCH。如果接受,浏览器才会发真正的请求。
JSONP
步骤
- 假设 a.com:8888 想把 GET /data 共享给 b.com:7777
- b.com 提前放置一个回调把回调名告诉 a.com
- b.com 通过
<script>标签来请求 /data - a.com 后端改造/data,把JSON变成JSONP
缺点
<script>只能发 get 请求- 无法定向分享(可以用 referrer 实现定向)
- 这是后端的活
JSONP的本质
取巧
- 由于
<script>标签不受同源策略约束,可以请求任意JS,所有后端直接把数据放到了JS里。对回调的使用是JSONP的点睛之笔
反向代理
一般通过 nginx 配置实现 步骤
- 假设 a.com:8888 想把 GET /data 共享给 b.com:7777
- b.com 后端提供一个 /data
(nginx配置如下)
- b.com 前端通过AJAX访问b.com/data
- b.com/data 向 a.com/data发请求,得到响应之后给 b.com 的前端