一.同源策略——浏览器的安全策略
URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示它们是同源的。
浏览器的同源策略限制了来自不同源的“document”或脚本,对当前“document”读取或设置某些属性,从一个域上加载的脚本不允许访问另一个与的文档属性。
在浏览器中,等标签都可以加载跨域资源而不受同源策略限制。但浏览器限制了JavaScript的权限使其不能读、写加载的内容。同源策略只对网页的HTML文档做了限制,对加载的其他静态资源如:JavaScript、CSS、图片等仍然认为属于同源。document对象的domain属性存放着装载文档的服务器的主机名,可以设置它。例如:来自“blog.csdn.net”和来自“bbs.csdn.net”的页面,都将document.domain设置为“csdn.net”,则来自两个子域名的脚本即可相互访问。处于安全考虑,不能设置为其他domain。比如:http://www.csdn.net/不能设置为sina.com。
被同源策略限制的行为包括:cookie、localStorage和IndexDB无法读取;DOM无法获得;AJAX请求不能发送;
二.跨域方法
1.JSONP
AJAX请求受同源策略的影响,不允许进行跨域请求,而script标签的src属性中的连接却可以访问跨域的JS脚本,利用这个特性,服务器端不再返回JSON格式的数据,而是返回一段调用某个函数的JS代码,在src中进行了调用,这样子就实现了跨域。JSONP只能发送get请求,且需要服务器端配合。
例如:
其中,callback=funcName是我们传给服务器的,服务器将我们需要的JSON数据作为参数传给这个函数,然后返回这个函数调用的JS文件。而这个funcName函数,需要我们在当前的文档中已经声明。
2.通过修改document.domain来跨子域
两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain共享cookie或者处理iframe。这种方法只适用于cookie和iframe窗口。cookie同源策略只关注域名,忽略协议和端口号。
3.使用片段标识符来进行跨域
父窗口可以把信息写入子窗口的片段标识符,子窗口通过监听hashchange事件得到通知。子窗口也可以改变父窗口的片段标识符。
4.使用window.name来进行跨域
window对象有一个name属性,在一个窗口的声明周期内,窗口载入的所有页面都是共享一个window.name的,每个页面对window.name都有读写的权限。这个属性的最大特点就是,无论是否同源,只要在一个窗口里,前一个网页设置了这个属性,后一个网页就可以读取它。
5.window.postMessage
window.postMessage是一个跨文档通信API,允许跨窗口通信,不论这两个窗口是否同源。
父窗口向子窗口发消息调用postMessage(“data”,URL);
子窗口设置监听message事件:window.onmessage=function(e){};
子窗口向父窗口发送消息:window.opener.postMessage(“data”,URL);
6.通过webSocket进行跨域
webSocket协议不受同源策略限制,只要服务器支持就可以通过它进行跨域通信。
7.通过设置代理的方法跨域
通过在同域名下的web服务器端创建一个代理,将浏览器的请求先发送给同域名下的服务器,由这个服务器去跨域请求其他不同域的服务器数据,然后在将数据传送回给前端。这里,同源限制只对客户端浏览器存在,对服务器端不存在同源限制。
8.CORS 跨域资源分享
CORS允许任何类型的请求,CORS需要浏览器和服务器同时支持,它允许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。整个CORS通信的过程,都是浏览器自动完成的,不需要用户参与。浏览器一旦发现AJAX请求跨域,就会自动添加一些附加的头信息,有时还会多出一次附加的请求。
Origin字段:说明本次请求来自哪个源,服务器可以根据这个值决定是否同意这次请求;
服务器通过Acess-Control-Allow-Origin来设置允许响应来自哪些源的请求。