摘要:同源策略浏览器出于安全方面的考虑,不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。传回后回调函数立即执行参数是后端产生的数据从而实现相应的功能。
同源策略
浏览器出于安全方面的考虑,不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。
同源指的是:
同协议
同域名
同端口
作用:保证用户信息的安全,防止恶意的网站窃取数据
例1:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。除此之外,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。(因为浏览器同时还规定,提交表单不受同源政策的限制)
例2:恶意网站的页面通过iframe嵌入了银行的登录页面(二者不同源),如果没有同源限制,恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码,从而造成相关的风险。
对于当前页面来说页面中 JS 文件的域不重要,重要的是当前页面所在的域与 脚本中涉及到的域(例如xht的open方法的url)是否同源
跨域跨域:浏览器出于安全方面的考虑设置了同源策略来限制不同域之间的交互,但是也阻碍了不域之间的协助。为了实现不同域之间的交互、协作,因此需要“跨域”。
跨域窗口通信 降域降域获取同一 Cookie:Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。但是,两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain 共享 Cookie。
example:A 网页是 http://w1.example.com/a.html,B 网页是http://w2.example.com/b.html,那么只要设置相同的 document.domain,两个网页就可以共享 Cookie。
JavaScript
// A网页和B网页设置相同的 document.domain document.domain = "example.com"
// A网页通过脚本设置 Cookie document.cookie = "test1 = hello";
// B网页可以获取到该 Cookie var otherCookie = document.cookie;
降域使不同源的iframe窗口和父窗口相互通信:如果两个网页不同源,就无法拿到对方的
DOM。典型的例子是 iframe 窗口和与父窗口无法通信。如果两个窗口一级域名相同,只是二级域名不同,那么设置 document.domain 属性,就可以规避同源政策,拿到
DOM。
A 网页:URL: http://a.yanxin.com:8080/a.html
HTML
使用降域实现跨域
script
iframe 中的 B 网页:URL: http://b.yanxin.com:8080/b.html
HTML
script
postMessageHTML5为了解决跨域问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。
这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。
目的:向另一个地方传递数据,另一个地方指的是:包含在当前页面的
window.postMessage() 方法被调用时,会在所有页面脚本执行完毕之后向目标窗口派发一个 MessageEvent 消息。 * otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow:其他窗口的一个引用(相对于当前的窗口的其他窗口),比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
message将要发送到其他 window的数据
targetOrigin:指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。
注意:如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是*。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。
示例
页面 A: http://a.yanxin.cn:8080/a.html。
在页面 A 中 打开页面 B: http://b.yanxin.cn:8080/b.html
当点击页面 A 上的 button 时,向页面B传输消息 "hello world"
HTML
script
为页面 B 的 window 添加监听器
当页面 B 收到 Message 时,在控制台中输出收到的消息,并提示 "hello"
CORS: Cross-Origin Resource Sharing, 跨源资源共享,是W3C的一个工作草案,定义了在必须访问跨源资源时,浏览器与服务器应该如何沟通,它是一种 ajax跨域请求资源的方式,支持现代浏览器,IE支持10以上。
实现过程:当使用 XMLHttpRequest发送请求时,浏览器发现该请求不符合同源策略,会自动给该请求加一个请求头:Origin,并将请求发送。服务器端收到请求后,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器收到响应后判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。整个CORS通信过程,都是浏览器自动完成,不需要用户参与
实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
详细流程:
1.浏览器发现这次请求不符合同源策略,就自动在头信息之中,添加一个Origin字段。
GET /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
在上面的头信息中,Origin字段表明了本次请求来自哪个源:协议、域名、端口。
2.该请求到达服务器后,服务器会根据这个值来判断是否接受请求。如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段(如下所示)。如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。
Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8
3.浏览器收到响应后判断该相应头中是否包含Origin的值,如果响应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获,这时我们无法拿到响应数据。如果有则浏览器会处理响应,我们就可以拿到响应数据。
JSONP基本思想是,网页通过添加一个