跨域怎么解决

跨域解决主要有以下⼏种:
  • JSONP
  • CORS
  • Nginx代理
  • document.domain
  • window.name
  • postMessage+iframe

1.JSONP

我们知道写 HTML 代码的时候,加⼊图⽚链接就不会有获取不到图⽚的问题。这是因为图
⽚资源并没有进⾏ ajax 请求,⽽且 script 标签是没有同源策略的,可以进⾏资源请求,可
以说是⼀个前端设计的漏洞。
// 1.回调函数
function handleResponse(data){
console.log(data);
}
// 2.动态创建 script
var script = document.createElement('script');
script.src = 'http://test.com/json?callback=handleResponse';
document.body.insertBefore(script,document.body.firstChild);
利⽤ script 标签⽴即下载并执⾏的特性,我们就可以在回调函数中拿到返回来的数据。那
么是不是所有的情况都可以呢?显然不是的。虽然实现是⽐较简单的操作,但是有缺点:
1. 仅限于 GET 请求
2. 有安全问题,万⼀有恶意代码返回,前端⽆法阻⽌
3. ⽆法检测请求是否成功

2.CORS

CORS是跨域资源共享(Cross-origin resource sharing)

要想利⽤这个技术关键是在于服务端,设置返回的 Access-Control-Allow-Origin 响应头允
许跨域操作,发送请求时有两种情况:
  • 简单请求
  • 复杂请求
①简单请求
当使⽤以下⽅法之⼀:
  • GET
  • HEAD
  • POST
Content-Type 的值为以下之⼀:
  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

才会发起简单请求,浏览器判断是简单请求的话就会在请求头添加 origin 字段,值是发起
请求的所在的源。服务端收到请求后会判断 origin 是否在⾃⼰的许可范围,如果不在就拒
绝,如果在就会有以下的响应头添加:
  • Access-Control-Allow-Origin (必选):告诉客户端我接受请求,值为 origin 的值,若
    允许所有源请求就会返回 *
  • Access-Control-Allow-Credentials(可选):告诉浏览器发送请求时携带 Cookie
    true 表⽰允许 false 表⽰禁⽌。
  • Access-Control-Expose-Headers(可选):额外给客户端返回的头部字段。
②复杂请求
复杂请求会有两次,第⼀次是发送⼀个预检请求,使⽤的⽅法是 options ,询问服务器是
否允许我进⾏跨域请求资源。并且允许客户端⾃定义请求头的类型,询问服务器是否允
许。
OPTIONS /cors HTTP/1.1
Origin: http://test.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Custom-Header1,Custom-Header2
Host: target.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
然后服务器会进⾏验证,还会在响应头进⾏说明允许你的请求。
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61(Unix)
Access-Control-Allow-Origin: http://test.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Custom-Header1,Custom-Header2
Access-Control-Max-Age: 1728000
Content-type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
  • Access-Control-Allow-Origin :告诉客户端,允许你这个源的请求
  • Access-Control-Allow-Methods:告诉客户端,服务端允许的跨域 AJAX 请求的类
    型,也可进⾏ GET 或者 POST 请求
  • Access-Control-Allow-Headers:告诉客户端,服务端允许的发送请求时的⾃定义请
    求头
  • Access-Control-Max-Age: 告诉客户端预检请求的有效期,省去了多次的预检请求。
    也就是说, 1728000 秒内你可以直接发送真正的 AJAX 请求,不⽤每次询问

3.Nginx代理

nginx ⽬录下的 nginx.conf 修改,通过反向代理的⽅式来实现跨域请求。
# /所有以apis开头发起的请求会被分发到myserver
location ^~ /apis/ {
proxy_pass http://myserver; # 负载均衡名,写你请求的服务器地址
proxy_set_header X-real-ip $remote_addr;
proxy_set_header Host $http_host;
}

4.document.domain

该⽅式只能⽤于⼆级域名相同的情况下,⽐如 a.test.com b.test.com 适⽤于该⽅式。
只需要给⻚⾯添加 document.domain = 'test.com' 表⽰⼆级域名都相同就可以实现跨域。

5.window.name

window.name 有⼀个奇妙的性质,⻚⾯如果设置了 window.name ,那么在不关闭⻚⾯的
情况下,即使进⾏了⻚⾯跳转 location.href=... ,这个 window.name 还是会保留。
// 打开必应 https://www.bing.com/
// 打开控制台
> window.name
""
> window.name='test';
"test"
> location.href='http://www.google.com';
"http://www.google.com"
Navigated to https://www.google.com/> window.name
"test"

6.postMessage+iframe

这种⽅式通常⽤于获取嵌⼊⻚⾯中的第三⽅⻚⾯数据。⼀个⻚⾯发送消息,另⼀个⻚⾯判
断来源并接收消息
// 发送消息端
<div>
<div id="color">Frame Color</div>
</div>
<div>
<iframe id="child" src="http://b.com/b.html"></iframe>
</div>
window.onload=function(){
window.frames[0].postMessage('getcolor','http://b.com');
}
// 接收消息端
window.addEventListener('message',function(e){
console.log(e)
},false);
postMessage(data,origin) ⽅法接受两个参数:
  • data: 要传递的数据, html5 规范中提到该参数可以是 JavaScript 的任意基本类型或可
    复制的对象,然⽽并不是所有浏览器都做到了这点⼉,部分浏览器只能处理字符串参
    数,所以我们在传递参数的时候需要使⽤ JSON.stringify() ⽅法对对象参数序列化
  • origin:字符串参数,指明⽬标窗⼝的源,协议 + 主机 + 端⼝号 [+URL] URL 会被忽
    略,所以可以不写,这个参数是为了安全考虑, postMessage() ⽅法只会将 message
    传递给指定窗⼝,当然如果愿意也可以把参数设置为 "*" ,这样可以传递给任意窗⼝,
    如果要指定和当前窗⼝同源的话设置为 "/"
  • 33
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值