跨域
Q1:跨域的概念
A1:跨域指的是只要协议(protocol)、域名(host)、端口号(port)有任何一个不同,都被当做不同的域。而由于受到浏览器的同源策略的限制,无法正常进行交互通信。之所以会产生这种问题,思考下,要是随便引用外部文件,不同标签下的页面彼此引用,浏览器会懵逼的。
Q2:为什么会出现跨域问题?
A2:由于浏览器的同源策略限制,浏览器会拒绝跨域请求。 严格来说,浏览器并不是拒绝所有的跨域请求,实际上只拒绝跨域的读操作。看下浏览器的同源策略时如何执行的。Q3:什么才算做跨域?
- 通常浏览器允许跨域写操作(Cross-Origin writes),例如链接、重定向
- 通常浏览器允许跨域资源嵌入(Cross-Origin embedding),例如img、script标签
- 通常浏览器拒绝跨域读操作(Cross-Origin reads)。
A3:非同源请求,都是跨域。同源:如果两个页面拥有相同的协议、域名、端口,那么这两个页面属于用一个源(origin)。
跨域场景:
URL 主机(http://www.a.com) 是否跨域 说明
http://www.a.com/a.js 否 同源,在同一域名下
https://www.a.com/b.js 是 协议不同
http://www.a.com:8001/c.js 是 端口不同
http://a.com/d.js 是 主机不同(二级域名不同)
http://amd.a.com/d.html 是 同上,一级域名相同,二级不同
http://81.235.221.12/a.html 是 域名和对应的域名IP也不在相同的源下
同源策略
MDN 解释: 同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
浏览器的同源策略的目的就是为了防止 XSS,CSRF 等恶意攻击。
同源策略限制了以下行为
- Cookie、LocalStorage 和 IndexDB 无法读取
- DOM 和 JS 对象无法获取
- Ajax请求发送不出去
跨域方法
1.CORS(Cross-Origin Resource Sharing,跨域源资源共享)
CORS是W3C的一个工作草案,定义了在必须访问跨域源资源时,浏览器与服务器应该如何沟通。基本思想:使用自定义的HTTP头部让浏览器和服务器进行沟通,从而决定请求或响应是应该成功还是应该失败。简单来说,就是在发送请求时,附加一个额外的Origin头部,其中包含请求页面的源信息(协议、域名、端口),以便服务器根据这个头部信息来决定是否给与响应。
示例:Origin:http://www.nczonline.net。如果服务器认为这个请求可以接受,就会在Access-Control-Allow-Origin头部中回发相同的源信息(如果是公共资源,可以回发“*”)。示例:Access-Control-Allow-Origin:http://www.nczonline.net整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。IE8+:IE8/9需要使用XDomainRequest对象来支持CORS。
IE对CORS的支持
IE8+:IE8/9需要使用XDomainRequest对象来支持CORS浏览器提供了一个
XDR和XHR两个略有不同:
1.cookie不随请求发送,也不随响应返回2.只能设置请求头部信息中的Content-Type字段3.不能访问响应头部信息4.只支持Get和Post方法
其他浏览器对CORS的支持(IE不低于10)
如果要请求另一个域的资源师,使用标准的XHR对象并在open()方法中传入绝对URL即可。但有些限制:1.不能使用setRequestHeader()设置自定义头部2.不能接收和发送cookie3.调用getAllResponseHeaders()方法总返回空字符串。
2.JSONP跨域
jsonp跨域其实也是JavaScript设计模式中的一种代理模式。在HTML中利用<script>元素的这个开放策略,可以从不同域名下加载静态资源文件,因为通过script标签引入的js是不受同源策略的限制的。所以我们可以通过script标签引入一个js或者是一个其他后缀形式(如php,jsp等)的文件,此文件返回一个js函数的调用,而这种使用模式就是所谓的 JSONP。
let script = document.createElement('script');
script.src = 'https://sp0.baidu.com/su?wd=jiumozhi&callback=callback';
document.body.appendChild(script);
function callback(res) {
console.log(res);
}JSONP的优缺点
优点:JSONP不受同源策略的限制;兼容性更好;请求结束后可以通过回调函数来回去服 务器响应结果。
缺点:只支持GET请求;单向的数据请求。另外jsonp是从其他域加载代码执行,可能会出现安全上的问题。
3.document.domain+iframe 跨域
这种跨域的方式最主要的是要求主域名相同。浏览器中不同域的框架之间是不能进行js的交互操作的。例如:www.abc.com、a.abc.com、b.abc.com,三者的主域名都是abc.com。
不同的框架之间是可以获取window对象的,但却无法获取相应的属性和方法。比如,有一个页面,它的地址是www.abc.com/a.html , 在这个页面里面有一个iframe,它的src是abc.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的。这时候我们可以在www.abc.com/a.html和abc.com/b.html两个页面里设置document.domain = abc.com。注意只能把document.domain设置成自身或更高一级的父域,且主域必须相同。