摘要:浏览器同源政策以及跨域同源是指协议相同域名相同端口相同。同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。参考文献浏览器同源政策及其规避方法详解跨域问题
浏览器同源政策以及JS跨域
同源是指协议相同、域名相同、端口相同。同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
同源策略主要限制下面三种情况
Cookie 无法读取
DOM 无法获得
AJAX 请求不能发送
同源策略的本意是为了保证用户的信息安全。但有时也会带来不便,下面我们来看一下怎样规避同源的限制。
Cookie是服务器写入浏览器的一小段信息,只有同源的网页才能共享。
当两个网页的一级域名相同,只是二级域名不同的时候,我们可以通过设置document.domain来共享cookie
具体操作如下:
// 这两个网页的一级域名是相同的 http://h1.test.com http://h2.test.com //为两个页面设置相同的 document.domain document.domain = "test.com" // 这样两个网页就能共享`Cookie`
document.domain 不能随意设置,只能把document.domain设置成自身或更高一级的父域。
跨域文档通信如果两个网页不同源,就无法拿到对方的DOM,也无法进行通信。典型的例子是iframe窗口和window.open方法打开的窗口,它们与父窗口无法通信。
如果两个窗口一级域名相同,只是二级域名不同,那么设置上一节介绍的document.domain属性,就可以规避同源政策,拿到DOM。
关于通信,我们来看一下两种解决方案:
片段识别符片段标识符(fragment identifier)指的是,URL的#号后面的部分,如果只是改变片段标识符,页面不会重新刷新。
//父窗口可以把信息,写入子窗口的片段标识符 var src = originURL + "#" + data; document.getElementById("myIFrame").src = src; //子窗口通过监听hashchange事件得到通知 window.onhashchange = checkMessage; function checkMessage() { var message = window.location.hash; // ... } //同样的,子窗口也可以改变父窗口的片段标识符 parent.location.href= target + "#" + hash;window.postMessage
window.postMessage 是HTML5为了解决这个问题,引入了一个全新的API,无论两个窗口是否同源,都允许一个窗口向另一个窗口发送数据。
语法:
// otherWindow 其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象 //message 将要发送到其他 window的数据 //targetOrigin 接收消息的窗口的源(origin) otherWindow.postMessage(message, targetOrigin)
其他window可以监听message
//监听 message 事件 window.addEventListener("message", receiveMessage, false); //事件对象有一些常用的属性 //data 从其他 window 中传递过来的对象 //origin 消息发送方窗口的 origin //source 对发送消息的窗口对象的引用 function receiveMessage(event){ var origin = event.origin; //对发送消息的源进行验证 if (origin !== "http://example.org:8080") return; // ... }
实例:
窗口A : http://xiaoxiong.com
窗口B : http://miaomiao.com
显然这两个窗口不同源,不能通信,现在我们用postMessage进行通信。
//Awindow、Bwindow分别表示对 A B 窗口对象的引用 //B窗口向A窗口发消息 //如果A窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,消息就不能发送成功 //注意是用 Awindow 调用 postMessage 方法 Awindow.postMessage("hello!","http://xiaoxiong.com"); //在A中设置监听事件 window.addEventListener("message", receiveMessage, false); function receiveMessage(event){ console.log(event.origin);//http://miaomiao.com console.log(event.source);// Bwindow console.log(event.data);// hello! }AJAX
AJAX请求是我们经常用到的异步请求方法,但是AJAX请求是不能跨域的。
下面我们看一下常见的AJAX跨域方法
JSONP基本思想是,网页通过添加一个元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
function addScript(src) { var script = document.createElement("script"); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script, body.firstChild); } window.onload = function () { //请求的查询字符串有一个callback参数,用来指定回调函数的名字,这对于JSONP是必需的 addScript("http://test.com/a?callback=handler"); } //请求回来数据作为回调函数的参数 //作为参数的JSON数据被视为JavaScript对象 不用进行转换 function handler(data) { console.log(data); };
JSONP的优点:不受同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行;并且在请求完毕后可以通过调用callback的方式回传结果。
JSONP的缺点:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
WebSocketWebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
实例:
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com
上面代码中,有一个字段是Origin,表示该请求的请求源(origin),即发自哪个域名。
正是因为有了Origin这个字段,所以WebSocket才没有实行同源政策。因为服务器可以根据这个字段,判断是否许可本次通信。如果该域名在白名单内,服务器就会做出如下回应。
跨域资源共享 是官方的跨域解决方案。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
基本思想
CORS定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。
基本流程
浏览器发现是跨源AJAX请求,浏览器就直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。
GET /cors HTTP/1.1 Origin: http://xiaoxiong.com Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
上面的头信息中,Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。
如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。
如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。
Access-Control-Allow-Origin: http://xiaoxiong.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
CORS和JSONP对比,更为先进、方便和可靠。
1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。 2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。 3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS)。 4、 jsonp在调用失败的时候不会返回各种HTTP状态码。 5、在请求完毕后可以通过调用callback的方式回传结果。将回调方法的权限给了调用方。这个就相当于将controller层和view层终于分开了。我提供的jsonp服务只提供纯服务的数据,至于提供服务以后的页面渲染和后续view操作都由调用者来自己定义就好了。如果有两个页面需要渲染同一份数据,你们只需要有不同的渲染逻辑就可以了,逻辑都可以使用同 一个jsonp服务。
参考文献
浏览器同源政策及其规避方法
详解js跨域问题
window.postMessage
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/84269.html
摘要:概述同源策略是对代码能够操作哪些内容的一条完整的安全限制,也是由提出的一个著名的安全策略。同源策略的目的同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。 [TOC] 1、概述 同源策略是对JavaScript代码能够操作哪些WEB内容的一条完整的安全限制,也是由Netscape提出的一个著名的安全策略。所谓同源简单来说就是三个相同,**1、域名相同2、协议相同3、端口...
摘要:概述同源策略是对代码能够操作哪些内容的一条完整的安全限制,也是由提出的一个著名的安全策略。同源策略的目的同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。 [TOC] 1、概述 同源策略是对JavaScript代码能够操作哪些WEB内容的一条完整的安全限制,也是由Netscape提出的一个著名的安全策略。所谓同源简单来说就是三个相同,**1、域名相同2、协议相同3、端口...
摘要:补充同源策略还应该对一些特殊情况做处理,比如限制协议下脚本的访问权限。注意,该请求的查询字符串有一个参数,用来指定回调函数的名字,这对于是必需的。 1 前言: 首先对参考文章作者表示感谢,你们的经验总结给我们这些新手提供了太多资源。本文致力于解决AJAX的CORS问题,我在逻辑上进行了梳理:首先,系统的总结了CORS问题的起源---同源策略;其次,介绍JSONP这种仅能支持GET请求的...
摘要:补充同源策略还应该对一些特殊情况做处理,比如限制协议下脚本的访问权限。注意,该请求的查询字符串有一个参数,用来指定回调函数的名字,这对于是必需的。 1 前言: 首先对参考文章作者表示感谢,你们的经验总结给我们这些新手提供了太多资源。本文致力于解决AJAX的CORS问题,我在逻辑上进行了梳理:首先,系统的总结了CORS问题的起源---同源策略;其次,介绍JSONP这种仅能支持GET请求的...
阅读 1207·2023-04-26 01:38
阅读 1430·2021-11-15 11:39
阅读 3234·2021-09-22 15:43
阅读 2584·2019-08-30 15:55
阅读 2017·2019-08-30 14:17
阅读 2831·2019-08-29 14:16
阅读 3037·2019-08-26 18:36
阅读 2590·2019-08-26 12:19