CORS
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
什么是跨域
跨域指的是 通过js在不同的域进行通信或传输数据。比如通过
<img>
标签加载其他域的资源图片,<script>
标签加载其他域的js文件,或者通过js获取页面中不同域的框架中(iframe
)的数据。只要域名、协议、端口号有任何一个不同,就属于不同的域。
跨域方法
XMLHttpRequest对象
通过XHR实现Ajax通信的一个主要限制,来源于跨域安全策略。默认情况下,XHR 对象只能访问与包含它的页面位于同一个域中的资源。但是,浏览器(IE除外)都通过 XMLHttpRequest对象实现了对 CORS 的原生支持。在尝试打开不同来源的资源时,无需额外编写代码就可以触发这个行为。要请求位于另一个域中的资源,使用标准的 XHR对象并在 open() 方法中传入绝对 URL即可。比如:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status== 304){
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("get", "https://jsonplaceholder.typicode.com/users", true);
xhr.send(null);
Jsonp跨域
通过
<script>
标签加载其他域的资源,服务器端设置一个辅助函数配合前端回调函数,返回的是可执行的js把它作为回调函数的参数即可得到我们获取的数据。但缺点是只能进行get方法请求。
页面代码如下:
<!DOCTYPE html>
<html>
<head>
<title>Jsonp</title>
<meta charset="utf-8">
</head>
<body>
<div id="show"></div>
<script type="text/javascript">
function showData(data) {
console.table(data);
}
showData();
</script>
<script type="text/javascript">
window.onload = function(){
let script = document.createElement('script');
script.src = 'https://jsonplaceholder.typicode.com/users'+'?callback=showData';
document.body.appendChild(script);
}
</script>
</body>
</html>
Google控制台输出结果
跨文档消息传递
跨文档消息传送(cross-document messaging),有时候简称为 XDM,指的是在来自不同域的页面间传递消息。例如,www.aa.com域中的页面与位于一个内嵌框架p2p.aa.com域中的页面通信。
XDM 的核心方法是PostMessage。在 HTML5 规范中,除了 XDM部分之外的其他部分也会提到这个方法名,但都是为了同一个目的:向另一个地方传递数据。对于 XDM 而言,“另一个地方”指的是包含在当前页面中的 <iframe> 元素,或者由当前页面弹出的窗口。
postMessage() 方法接收两个参数:一条消息和一个表示消息接收方来自哪个域的字符串。第二个参数对保障安全通信非常重要,可以防止浏览器把消息发送到不安全的地方。
接收到 XDM 消息时,会触发 window 对象的 message 事件传递给 onmessage 处理程序的事件对象包含以下三方面的重要信息
data :作为 postMessage() 第一个参数传入的字符串数据。origin :发送消息的文档所在的域,例如 "http://www.wrox.com"
source :发送消息的文档的 window 对象的代理。这个代理对象主要用于在发送上一条消息的窗口中调用 postMessage() 方法。如果发送消息的窗口来自同一个域,那这个对象就是window
在 onmessage 处理程序中检测消息来源可以确保传入的消息来自已知的页面
检测方法如下
EventUtil.addHandler(window, "message",
function(event){
//确保发送消息的域是已知的域
if (event.origin == "http://www.wrox.com"){
//处理接收到的数据
processMessage(event.data);
//可选:向来源窗口发送回执
event.source.postMessage("Received!", "http://p2p.wrox.com");
}
});