跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,使用XMLHttpRequest进行跨域请求会被浏览器拦截。
由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。
跨域资源共享(CORS)
CORS是主流的跨域解决方案,所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)。
跨域请求默认不携带cookie,这时只需要服务端设置Access-Control-Allow-Origin,如果需要请求携带cookie(由于同源策略的限制,携带的不是当前页的cookie而是跨域请求接口所在域的cookie),则前后端都需要设置。
HTTP请求可以分为简单请求和复杂请求,CORS这两类请求按不同的策略进行跨域资源共享协商。
当HTTP请求出现以下两种情况时,浏览器认为是简单请求:
- 请求方法是GET、HEAD或者POST,并且当请求方法是POST时,Content-Type必须是application/x-www-form-urlencoded, multipart/form-data或着text/plain中的一个值。
- 请求中没有自定义HTTP头部。
对于简单跨域请求,浏览器要做的就是在HTTP请求中添加Origin Header,将JavaScript脚本所在域填充进去,向其他域的服务器请求资源。服务器端收到一个简单跨域请求后,根据资源权限配置,在响应头中添加Access-Control-Allow-Origin Header。浏览器收到响应后,查看Access-Control-Allow-Origin Header,如果当前域已经得到授权,则将结果返回给JavaScript。否则浏览器忽略此次响应。
对于复杂跨域请求浏览器在发送真实HTTP请求之前会先发送一个OPTIONS的预检请求,检测服务器端是否支持真实请求进行跨域资源访问,真实请求的信息在OPTIONS请求中通过Access-Control-Request-Method Header和Access-Control-Request-Headers Header描述,此外与简单跨域请求一样,浏览器也会添加Origin Header。
服务器端接到预检请求后,根据资源权限配置,在响应头中放入Access-Control-Allow-Origin Header、Access-Control-Allow-Methods和Access-Control-Allow-Headers Header,分别表示允许跨域资源请求的域、请求方法和请求头。
此外,服务器端还可以加入Access-Control-Max-Age响应头,允许浏览器在指定时间内,无需再发送预检请求进行协商,直接用本次协商结果即可。浏览器根据OPTIONS请求返回的结果来决定是否继续发送真实的请求进行跨域资源访问。
JSONP
拥有src属性和href属性的
代理跨域
同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨域问题。
通过代理服务器(域名与demo1相同,端口不同)做跳板机,反向代理访问demo2接口,还可以修改cookie中demo信息,方便当前域cookie写入。
postMessage跨域
使用postMessage跨域很简单,通过postMessageAPI对目标窗口发送数据,通过监听message事件接收数据,从而实现跨窗口的异域通讯。

WebSocket跨域
websocket协议没有同源策略的限制,而且它本身就有意被设计成可以跨域的一个手段。由于历史原因,跨域检测一直是由浏览器端来做,但是WebSocket出现以后,对于WebSocket的跨域检测工作就交给了服务端,浏览器仍然会带上一个Origin跨域请求头,服务端则根据这个请求头判断此次跨域WebSocket请求是否合法。
iframe跨域
document.domain + iframe跨域
如果主域相同只有子域不一样时,通过设置两个页面的document.domain都为主域名就实现了同域。
location.hash + iframe跨域
location.hash属性是一个可读可写的字符串,该字符串是URL的锚部分(从# 号开始的部分)。 通过location.hash跨域就是利用动态改变location.hash不会重载iframe的特性将要传递的数据放在url里,因此传递数据量有限、安全性也比较低。
window.name + iframe跨域
name是window对象的一个属性,当在iframe中加载新页面时,window.name不会发生变化。
给iframe赋值跨域的链接,加载完后触发onload事件,此时iframe已经拿到数据放在window.name里,因为浏览器同源策略没法直接拿iframe的name值,所以将iframe的地址改成同域名下的一个网页,在用contentWindow方法获取iframe的name值获取数据。
a.html:
b.html:
window.name值最大支持2M,如果给window.name赋值,window.name会调用类似toString的方法将赋给它的值转换成对应的字符串表示。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/175600.html