一、JSONP
1. JSONP原理:
(1)不存在跨域请求限制的标签:img、script、link、iframe、form,JSONP正是利用script标签的该特性实现跨域
(2)JSONP利用<script>标签不受跨域请求限制的特性,向服务器发送请求,并且将回调函数传递给服务器;服务器收到请求和函数后,以json格式作为回调函数的参数传递给它,也就是用json数据来填充回调函数,并返回数据到客户端;客户端收到服务器响应后执行回调函数,该回调函数可以用来处理服务器的返回数据。
2. JSONP跨域过程:
(1)创建函数func,用于处理服务器返回数据;
(2)创建<script>标签,通过src属性向服务器发送请求,并将函数func作为callback参数传递;
(3)服务器收到请求,将返回数据以json格式填充回调函数,比如:'func(' + JSON.stringfy(data) + '){...}';
(4)客户端接收服务器返回数据,执行回调函数。
3. 注意:
(1)传递给服务器的回调函数必须是全局函数,不然将无法执行;
(2)JSONP的实现仅仅依靠客户端是不够的,还需要服务器的支持;
(3)JSONP只能处理GET请求
4. 举例:
<script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
<script>
function callbackFunc(data){
console.log('服务端返回数据:', data)
}
$.ajax({
url: 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',
type: 'GET',
dataType: 'jsonp',
data: {'wd': '0'},
jsonp: 'callback',
jsonpCallback: 'callbackFunc',
success: (res)=>{
console.log('请求成功,返回数据为:',res);
},
error: (res)=>{
console.log('请求失败,返回数据为:', res);
}
})
</script>
jsonp与jsonpCallback:jsonp跨域时可以自定义的两个参数
① jsonp: 回掉函数名的参数名,默认callback。这个值用来替代在"callback=?"这种GET或POST请求中URL参数里的"callback"部分,比如{jsonp:'onJsonPLoad'}会导致将"onJsonPLoad=?"传给服务器。
② jsonpCallback: 为jsonp请求指定一个回调函数名。这个值将用来取代jQuery自动生成的随机函数名。 *这主要用来让jQuery生成度独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。 *你也可以在想让浏览器缓存GET请求的时候,指定这个回调函数名。
③指定jsonpCallback时可以将回调函数写在ajax外面做其他操作,不指定时不能这样做,只能在success里做操作
(2)JSONP实现vue跨域
<script>
var vue = new Vue( {
el: '#box',
data () {
return {
v1:"0"
}
},
mounted:function(){
let url = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su";
this.$http.jsonp(url, //请求路径
{
params: {wd: this.v1}, //请求参数
jsonp:'cb' //回调参数
}).then((res)=>{
vue.v1 = JSON.parse(res.bodyText).s;
console.log('请求成功!')
},()=>{
console.log("请求失败!")
})
}
});
</script>
二、CORS(跨域资源共享)
1. CORS基本思想:使用自定义的HTTP头部让浏览器和服务器通信
2. 简单请求与非简单请求:
(1)浏览器将CORS请求分成两类:简单请求和非简单请求。只要同时满足以下两大条件,就属于简单请求。
①请求方法是以下三种方法之一:
- HEAD
- GET
- POST
②HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值
application/x-www-form-urlencoded
、multipart/form-data
、text/plain
(2)对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin
字段。
(3)非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT
或DELETE
,或者Content-Type
字段的类型是application/json
。非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
3. CORS字段:
(1)Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时Origin
字段的值,要么是一个*
,表示接受任意域名的请求。
(2)Access-Control-Allow-Credentials
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true
,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true
,如果服务器不要浏览器发送Cookie,删除该字段即可。
(3)Access-Control-Request-Method
该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法。
(4)Access-Control-Request-Headers
该字段可选。该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段。
三、postMessage
1. postMessage允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递
2. 语法:
otherWindow.postMessage(message, targetOrigin, [transfer]);
(1)otherWindow:
其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
(2)message:
将要发送到其他 window的数据。它将会被结构化克隆算法序列化。这意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化。[1]
(3)targetOrigin:
通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;例如,当用postMessage传送密码时,这个参数就显得尤为重要,必须保证它的值与这条包含密码的信息的预期接受者的origin属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是*。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。
(4)transfer
:可选,是一串和message 同时传递的 Transferable
对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。