接触前端有几个月了,今天说一说我对前端跨域的认识和解决方案,其实在之前我对跨域并没有什么概念
只是听闻过这个恶名远扬的单词,直到有一天我遇到了他
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。如果两个页面的协议,端口(如果有指定)和主机都相同,则两个页面具有相同的源。我们也可以把它称为“协议/主机/端口 tuple”,或简单地叫做“tuple". ("tuple" ,“元”,是指一些事物组合在一起形成一个整体,比如(1,2)叫二元,(1,2,3)叫三元)。(mdn)
上边这一段话来自于MDN,反正在我看来这么一大段干(gou)净(pi)利(bu)落(tong)的话实在是很官方,
说白了跨域就是说 主机名(域名)、协议、端口号只要有其一不同,就为不同的域,那么这个时候你去请求的话就会发生跨域
总之就是浏览器的一种叫做同源策略限制的东西在搞事情
大概讲的是请求的时候会发送一个Origin报头到被请求的地址
然后被请求的地址返给请求者一个Access-Control-Allow-Origin响应头,如果值为*或者和Origin的站点对应,那么就可以请求,如果不对应就会跨域
同源策略限制这个东西我觉得主要就是针对请求,如果没有的话,假如你进入了一个需要登陆的网站,你登陆完成之后,浏览器保存了你的cookie,然后你在不退出的情况下中途访问了其他的恶意网站,这个恶意网站就可以盗取你的登陆信息去直接登陆你的账号
还有一种就是这个同源策略限制了dom的查询比如说我们项目中用到过iframe 这个标签 ,他可以将一个html页面嵌入到当前的页面中,如果说一个网站把另一个你信任的网站通过iframe嵌入到自己的网站的话,那么你输入的一切东西都会被人家看的一清二楚,有了同源策略的话一般都需要去代理其他域名或者加入白名单,才能引入那个域名的html,
可以说是同源策略限制给了用户一个基本的保护
一直以来,自从我接触前端以来,我就在不停的和url打交道,but我之前都是管这个东西叫域名的,
很是尴尬,
url中文叫做统一资源定位符,是互联网上一处资源的地址,一个完整的url主要有一下及部分组成
script标签,浏览器禁止了跨域的请求访问,但是可以引入其他域的script脚本,并能使用其中的方法,常用的浏览器可以通过load事件判断script是否加载完毕,ie是通过readystatechange属性
postMessage ,这是html5新加的一个新特性,跨文档消息传输Cross Document Messaging。
window.postMessage()方法可以安全的实现跨域通信,当方法被调用的时候,会在所有页面的脚本执行完毕之后,向目标窗口发送一个messageEvent的一个消息
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
message
将要发送到其他 window的数据。
targetOrigin
通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"星号"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。
transfer 可选
是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
在接收的window窗口下边可以增加一个监听
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
//回调
}
message对象有四个属性
source属性 发送消息的窗口对象的引用
JsonP跨域
上边说了script方法 其实这个可以说成是一种,另外补充下比如img link等 都具有跨域访问的能力
jsonp其实使用这个特性来实现跨域的,在jsonp里边可以定义回调函数,jsonp并不能替代请求,记得有一次微信公众号获取token跨域,jsonp并不能达到相应的效果,感觉jsonp 就是把script标签给封装了一下
W3C推荐了一种跨域的访问验证的机制,即CORS(Cross-Origin Resource Sharing 跨源资源共享)。 这种机制让Web应用服务器能支持跨站访问控制,使跨站数据传输更加安全,减轻跨域HTTP请求的风险。
现在的各主流的浏览器都会对动态的跨域请求进行特殊的验证处理。验证处理分为简单请求验证处理和预先请求验证处理。
之一的时候,浏览器会直接发送跨域请求,并在请求头中携带访问地址的header,
当服务端接收到请求之后,会根据自己的跨域规则,通过Access-Control-Allow-Origin和Access-Control-Allow-Methods响应头,来返回验证结果。
如果验证失败则不会返回资源
与简单请求对应的 ,上述的六个条件,只要有一条不符合,浏览器在接收到请求的时候并不会立即执行请求的代码,而是会先发送一个option请求,用于访问服务器是否符合规范
正常来讲我们发送请求,比如post请求的时候,浏览器也会默认给我们加上一个options请求,他的主要用途就是获取服务器支持的http请求房和,和判断安全,
如果验证成功则会发送需要执行的请求,如果验证失败的时候则会返回一个403的状态
以上方法基本上就可以应对大部分的跨域的需求了,还有一些其他的方法比如说document.domain+iframe
如果是都在一个主源里边的话可以用一下,对于不同的源是无能为力的,沾个例子
//www.a.com上的a.html
document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.a.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
var doc = ifr.contentDocument || ifr.contentWindow.document;
// 在这里操纵b.html
alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};
//script.a.com上的b.html
document.domain = 'a.com';
比如上边这个www.a.com和script.a.com 他们的js是可以互通的,然后说明一下就是我们在日常用经常看到的www开头的域名 其实是二级域名
这里例子里边a.com才是主域名
以上是我对跨域和常用的解决方法的一些认知,有不足之处请多批评,我要去写bug了
原文:https://www.cnblogs.com/netUserAdd/p/11028853.html