@ranger-01
2018-05-22T13:14:22.000000Z
字数 3318
阅读 1129
cors web
理解跨域首先必须要了解同源策略。同源策略是浏览器上为安全性考虑实施的非常重要的安全策略。
何谓同源:
URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。
URL 说明 是否允许通信http://www.a.com/a.jshttp://www.a.com/b.js 同一域名下 允许http://www.a.com/lab/a.jshttp://www.a.com/script/b.js 同一域名下不同文件夹 允许http://www.a.com:8000/a.jshttp://www.a.com/b.js 同一域名,不同端口 不允许http://www.a.com/a.jshttps://www.a.com/b.js 同一域名,不同协议 不允许http://www.a.com/a.jshttp://70.32.92.74/b.js 域名和域名对应ip 不允许http://www.a.com/a.jshttp://script.a.com/b.js 主域相同,子域不同 不允许(cookie这种情况下也不允许访问)http://www.a.com/a.jshttp://a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)http://www.cnblogs.com/a.jshttp://www.a.com/b.js 不同域名 不允许
同源策略:
浏览器的同源策略,限制了来自不同源的"document"或脚本,对当前"document"读取或设置某些属性。
从一个域上加载的脚本不允许访问另外一个域的文档属性。
举个例子:
比如一个恶意网站的页面通过iframe嵌入了银行的登录页面(二者不同源),如果没有同源限制,恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码。
在浏览器中,<script>、<img>、<iframe>、<link>等标签都可以加载跨域资源,而不受同源限制。JSONP实现跨域就是利用了这一点。
修改document.domain的方法只适用于不同子域的框架间的交互。
有跨域问题
有一个页面,它的地址是http://www.damonare.cn/a.html
<script type="text/javascript">function test(){var iframe = document.getElementById('ifame');var win = document.contentWindow;//可以获取到iframe里的window对象,但该window对象的属性和方法几乎是不可用的var doc = win.document;//这里获取不到iframe里的document对象var name = win.name;//这里同样获取不到window对象的name属性}</script><iframe id = "iframe" src="http://damonare.cn/b.html" onload = "test()"></iframe>
// 在页面http://www.damonare.cn/a.html 中<iframe id = "iframe" src="http://damonare.cn/b.html" onload = "test()"></iframe><script type="text/javascript">document.domain = 'damonare.cn';//设置成主域function test(){alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象}</script>// 在页面http://damonare.cn/b.html 中也设置document.domain:<script type="text/javascript">document.domain = 'damonare.cn';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同</script>
利用标签没有跨域限制的“漏洞”(历史遗迹啊)来达到与第三方通讯的目的
// jQuery$.ajax({url: "http://tonghuashuo.github.io/test/jsonp.txt",dataType: 'jsonp',jsonp: "callback",jsonpCallback: "dosomething"}).done(function(res) {console.log("success");console.log(res);}).fail(function(res) {console.log("error");console.log(res);});// js<script>// 实现回调函数,这里没有了 jQuery 的封装,必须手动指定并实现var dosomething = function(data){console.log(data);};// 提供 JSONP 服务的 URL 地址,查询字符串中加入 callback 指定回调函数var url = "tonghuashuo.github.io/test/jsonp.txt?callback=docomething";// 创建 <script> 标签,设置其 src 属性var script = document.createElement('script');script.setAttribute('src', url);// 把 <script> 标签加入 <body> 尾部,此时调用开始。document.getElementsByTagName('body')[0].appendChild(script);// 因为目标 URL 是一个后台脚本,访问后会被执行,返回的 JSON 被包裹在回调函数中以字符串的形式被返回。// 返回的字符串放入 <script> 中就成为了一个普通的函数调用,执行回调函数,返回的 JSON 数据作为实参被传给了回调函数。</script>
$result = "{'data':'JSONP Works'}"; // 这里省略了数据库查询等操作,直接给出返回值$callback = $_GET['callback']; // 最好加上判空和默认值,以防拿不到参数echo $callback."(".$result.")";// 返回的结果// dosomething({"data":"JSONP Works"});
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
两种请求
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求。

简单请求
对于简单请求,浏览器直接发出CORS请求
CORS_ORIGIN_WHITELIST不包含origin

CORS_ORIGIN_WHITELIST包含origin.

非简单请求
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
CORS_ALLOW_METHODS不包含header rainbow

CORS_ALLOW_METHODS包含header rainbow
