要了解跨域首先需要了解同源策略。
同源策略
浏览器出于安全的考虑,当页面向非本域(同协议,同域名以及同端口)的接口请求数据时,无法读写对方的资源。虽然这些限制是必要的,但是也会使合理的用途受到影响,因此就需要跨域,绕过上述限制获取数据。需要注意的是,同源策略是浏览器的限制,换个场景则不一定存在,比如微信浏览器、服务端发请求等。
一、JSONP(JSON with padding) 实现跨域
JSONP是一种通过加载<script>
标签绕过同源策略来请求数据的javascript模式。
HTML的<script>
标签可以调用服务器提供的js脚本,使用<script>
标签向某个链接发送请求获取数据时,服务器返回的是JSON格式的数据,直接作为js去执行必然会报错。则我们可以提前在页面声明一个函数,并将函数名通过接口传参的方式传递给后台,当后台解析url的pathname得到函数名时使用“函数名(原始数据)”的形式发送给前端,前端在收到数据时则可以直接执行该函数,在函数内部处理原始数据即可。
/* req.js */
<script>
function parseResponse(ret){
console.log(ret);
}
</script>
<script type="application/javascript"
src="http://server.example.com/Users/student.json?callback=parseResponse">
</script>
二、CORS(Cross-Origin Resource Sharing) 实现跨域
cors是一种ajax跨域请求资源的方式,支持现代浏览器及IE10以上。cors的请求分为简单请求(simple request)和非简单请求(not-so-simple request)两类。在此主要介绍简单请求的实现方式。
当使用 XMLHttpRequest 发送请求时,浏览器发现请求不符合同源策略时,会给该请求加一个请求头:Origin(用来说明本次请求来自哪个源(协议 + 域名 + 端口)),后台会进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。
使用 XMLHttpRequest发送ajax请求如下:
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://127.0.0.1:8080/getNews', true)
xhr.send()
xhr.onload = function(){
appendHtml(JSON.parse(xhr.responseText))
}
当在浏览器通过http://localhost:8080/index.html
打开页面时,会向http://127.0.0.1:8080/getNews
请求数据,此时浏览器检测属于跨域请求,则会在Requese Headers
中添加Origin: http://localhost:8080
,后端服务器会在返回的Response Headers
中包含Access-Control-Allow-Origin: http://localhost:8080
,此时包含origin的值,则浏览器会处理响应数据。
三、降域
举例来说,A网页是http://w1.example.com/a.html
,B网页是http://w2.example.com/b.html
,那么只要设置相同的document.domain
,则可以互相访问数据。
document.domain = 'example.com';
四、window.postMessage()
··window.postMessage()方法被调用时,会在所有页面脚本执行完毕之后(e.g., 在该方法之后设置的事件、之前设置的timeout 事件,etc.)向目标窗口派发一个 MessageEvent
消息。目标窗口若要接收消息则只需要监听window的message事件即可。
/*postMessage方法的调用格式*/
otherWindow.postMessage(message, origin);
- otherWindow是对要发送消息的窗口的一个引用
- message 是要发送到其他window的数据
- origin 用于指定哪些窗口能接收到消息事件
/*接收消息的页面的处理*/
window.addEventListener("message", receiveMessage(e){
if(e.source!=window.parent) return;
var color=document.querySelector('.container').style.backgroundColor;
window.parent.postMessage(color,'*');
},false)
网友评论