所谓跨域,顾名思义,跨到了另外的域,域不仅仅指的是不同的域名网站,可能同一个域名不同的端口号也算不同的域。浏览器是有规则的,只要协议、域名、端口有任何一个不同,都被当作是不同的域。协议指的是http,或者https等。
这个叫浏览器的同源策略(same-origin policy),为什么要这样规定呢,原因之一就是为了安全。
所以跨域正是利用了上面几点,比如jsonp就是利用的加载js文件的功能,比如在<script src="..."></script>
中的src指定为目标网站的js,同理,还有跨域攻击也可以利用<image src="..." />
的功能。还有iframe更能直接加载别的网站的内容到自己的网站里来。
这前面几种可以说是技巧,说句不好听的就是浏览器的漏洞,浏览器并未从正面上支持跨域,而且上面的几种跨域方法也是有各种局限,比如jsonp的方法,只能用GET方法,iframe方法是能直接加载内容到网站上,但是本网站和iframe的数据交互也是一个头疼的地方。
JSONP原理
ajax请求受同源策略影响,不允许进行跨域请求,而script标签src属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域。
毕竟从iframe加载内容到本站后,是存在着数据交互的,可以用document.domain
,window.name
,不过这些方法都能用,且有效,不过总不尽完美,存在着各种各样的局限。
然而HTML5引进了一个叫window.postMessage方法来跨域传送数据,这个倒是不错,不过也是利用了iframe。
除此之外,还有flash,服务器代理等跨域方法,但是本章要介绍的是浏览器或服务器的跨域方法,它的名字叫CORS。
CORS全称是Cross-Origin Resource Sharing,跨域资源共享,这是浏览器的标准,也算是协议,基本上现代浏览器都支持,除了奇葩浏览器,例如IE8、IE9,只支持部分特性。
使用它,需要服务器端和客户端两方面的准备,服务器端我们选择nginx作为测试,客户端只是js罢了。
nginx服务监听在localhost的8080端口,而现在有一个网站运行localhost的3000端口,需要跨域到nginx那台服务器。
现在开始测试之旅,要在浏览器模拟跨域请求,只需三行js代码。
var xhttp = new XMLHttpRequest(); xhttp.open("GET", "http://localhost:8080", true); xhttp.send();
我们在服务器端设置一下,让Origin:http://localhost:3000
这个来源域被允许访问。
location / { add_header 'Access-Control-Allow-Origin' '*'; }
原来,浏览器在用XMLHttpRequest
发起跨域请求的时候,它在请求头带了Origin
这个项,而服务器,在响应头信息中是有响应Access-Control-Allow-Origin
这项的,两者比较一下,如果匹配,则请求成功,不匹配就不成功,不过,服务器那边还是照常执行。
在测试的时候需要注意的事,有可能会发现改了nginx的配置,浏览器发出的跨域请求却没生效,这可能是因为浏览器cache的原因,只要清除浏览器的cache,再重新发起请求就好了。
备注:内容参考来源于:https://www.rails365.net/articles/cong-kua-yu-dao-cors-yi