Open innerWang opened 5 years ago
浏览器出于安全的考虑,当页面向非本域(同协议,同域名,同端口)的接口请求数据时,无法读写对方的资源,这些限制会使合理的用途受到影响,因为就需要跨域,绕过上述限制获取数据。需要注意的是,同源策略是浏览器的限制,换个场景不一定存在,比如微信浏览器,服务端发请求等。
JSONP是一种通过加载<script>标签绕过同源策略来请求数据的javascript模式。
<script>
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 是一种 ajax 跨域请求资源的方式,支持现代浏览器及IE10以上,需要后端支持才可实现。cors 的请求分为简单请求(simple request)和非简单请求(not-so-simple request)两类。在此主要介绍简单请求的实现方式。
在向某一个接口发送 ajax请求数据时,浏览器检测到该接口不属于本域,则会在请求头上添加 Origin字段表明本次请求来自哪个源。
Origin: http://localhost:8080
服务端在接收到请求后会进行处理,确定接收请求则会在响应报文中设置响应头的字段:
Access-Control-Allow-Origin: http://localhost:8080
浏览器在收到响应后会判断响应头的上述 ACAO 字段是否包含 Origin的值,若包含,则处理响应,可成功获取响应数据;若不包含,浏览器会直接驳回,此时我们无法拿到响应数据。
window.postMessage()可实现如 页面与其弹出窗口(使用了window.open()) 或 页面与其嵌入的iframe 等窗口之间的跨域通信。该方法被调用时,会在所有页面脚本执行完毕后向目标窗口派发一个 MessageEvent 事件。
MessageEvent
targetWindow.postMessage(message, targetOrigin, [transfer])
接收方则可以通过监听message事件,检查事件的 origin/source属性,判断来源可信,则可以进行处理。 在此需要关注MessageEvent的几个属性:
示例如下:
//pageA <div class="parent"> pageA <button class="open">新建窗口</button> <button class="send">发送消息</button> </div> <script> let btnOpen = document.querySelector('.open') let btnSend = document.querySelector('.send') let childWindow = null // 打开pageB btnOpen.addEventListener('click',()=>{ childWindow = window.open('http://localhost:3002/index.html') }) //给PageB 发送消息 btnSend.addEventListener('click',()=>{ childWindow.postMessage('hello child','http://localhost:3002') }) //监听messageEvent window.addEventListener('message',(e)=>{ console.log(e) if(e.origin != "http://localhost:3002"){ console.log('not valid origin') return } console.log('get message from child: '+ e.data) }) </script>
//pageB <div class="parent"> pageB </div> <script> window.addEventListener('message',(e)=>{ console.log(e) if(e.origin != "http://localhost:3000"){ console.log('not valid origin') return } console.log('get message: '+ e.data) e.source.postMessage('hello parent','http://localhost:3000') }) </script>
1. 同源策略
浏览器出于安全的考虑,当页面向非本域(同协议,同域名,同端口)的接口请求数据时,无法读写对方的资源,这些限制会使合理的用途受到影响,因为就需要跨域,绕过上述限制获取数据。需要注意的是,同源策略是浏览器的限制,换个场景不一定存在,比如微信浏览器,服务端发请求等。
2. JSONP(JSON with padding)实现跨域
JSONP是一种通过加载
<script>
标签绕过同源策略来请求数据的javascript模式。HTML的
<script>
标签可以调用服务器提供的js脚本,使用<script>
标签向某个链接发送请求获取数据时,服务器返回的是JSON格式的数据,直接作为js去执行必然会报错。则我们可以提前在页面声明一个函数,并将函数名通过接口传参的方式传递给后台,当后台解析url的pathname得到函数名时使用 “函数名(原始数据)” 的形式发送给前端,前端在收到数据时则可以直接执行该函数,在函数内部处理原始数据即可。3. CORS(Cross-Origin Resource Sharing) 实现跨域
cors 是一种 ajax 跨域请求资源的方式,支持现代浏览器及IE10以上,需要后端支持才可实现。cors 的请求分为简单请求(simple request)和非简单请求(not-so-simple request)两类。在此主要介绍简单请求的实现方式。
在向某一个接口发送 ajax请求数据时,浏览器检测到该接口不属于本域,则会在请求头上添加 Origin字段表明本次请求来自哪个源。
服务端在接收到请求后会进行处理,确定接收请求则会在响应报文中设置响应头的字段:
浏览器在收到响应后会判断响应头的上述 ACAO 字段是否包含 Origin的值,若包含,则处理响应,可成功获取响应数据;若不包含,浏览器会直接驳回,此时我们无法拿到响应数据。
4. 使用 window.postMessage() 方法实现跨域
window.postMessage()可实现如 页面与其弹出窗口(使用了window.open()) 或 页面与其嵌入的iframe 等窗口之间的跨域通信。该方法被调用时,会在所有页面脚本执行完毕后向目标窗口派发一个
MessageEvent
事件。接收方则可以通过监听message事件,检查事件的 origin/source属性,判断来源可信,则可以进行处理。 在此需要关注
MessageEvent
的几个属性:示例如下: