【整理】跨域的几种方式

jsonp

说说json与jsonp

jsonp原理是动态添加一个script标签,script标签的src属性是没有跨域限制的。

在访问的url里传入回调函数及参数。

缺点:

  • 只支持get不支持post
  • 只支持http请求这种情况,不能解决不同于两个页面之间如何进行JavaScript调用的问题
  • jsonp请求失败时不返回http状态码

CORS

HTTP访问控制(CORS)

cors请求分为简单请求与非简单请求

简单请求

若请求满足所有下述条件,则该请求可视为简单请求

  • 使用一下方法之一
    • get
    • head
    • post
  • Content-Type的值仅限于一下三者:
    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded
  • 请求中的任意XMLHttpRequestUpload对象均没有注册任何事件监听器;XMLHTTPRequestUpload对象可以使用XMLHttpRequest.upload属性访问
  • 请求中没有使用ReadableStream对象
非简单请求

与简单请求不同是的,非简单请求需==使用options方法发起一个预检请求到服务区,以获知服务器是否允许该实际请求==。

预检请求与实际请求区别

  • 首部字段Access-Control-Request-Method告知服务器实际使用的请求方法
  • Access-Control-Request-Headers告知服务器实际请求将携带两个自定义请求首部字段X-PINGOTHER与Content-Type

服务器据此决定改实际请求是否被允许。

大多数浏览器不支持预检请求的重定向。如果一个预检请求发生了重定向,浏览器将报告错误。

避免改报错方法:

  • 在服务端去掉对预检请求的重定向
  • 将实际请求变成一个简单请求

document.domain

该方法只能用于二级域名相同的情况,比如a.test.com和b.test.com

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//a.html
<iframe src="http://b.test.com/b.html" id="iFrame" onload="load()"></iframe>

<script>
document.domain = "test.com"
function load() {
console.log(document.getElementById("iFrame").contentWindow);
}
</script>


//b.html
<script>
document.domain = "test.com"
</script>

window.name

name值在不同的页面加载后依旧存在,并且可以支持非常长的那么值(2MB)

1
2
3
4
5
6
7
8
9
10
11
12
13
//a.html
<script>
window.name = "messages from a";
setTimeout(function() {
window.location = "b.html";
}, 3000);
</script>


//b.html
<script>
console.log(window.name); //messages from a
</script>

window.postMessage

postMessage是HTML5 XMLHttpRequest Level2中可以跨域操作的window属性之一,可以解决一下方面的问题

  • 页面和其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的iframe消息传递
  • 上面三个场景的跨域数据传递

postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//a.html
<iframe src="http://localhost:8080/b.html" id="iFrame" onload="load()"></iframe>

<script>
function load() {
var iframe = document.getElementById("iFrame");
iframe.contentWindow.postMessage("messages from a");
}
</script>


//b.html
<script>
window.onmessage = function(e) {
e = e || event;
console.log(e.data); //messages from a
}
</script>

参考资料:

说说json与jsonp

HTTP访问控制(CORS)

js中几种实用的跨域方法原理详解

九种跨域方式实现原理