zoukankan      html  css  js  c++  java
  • 跨域与常用解决方法

    接触前端有几个月了,今天说一说我对前端跨域的认识和解决方案,其实在之前我对跨域并没有什么概念
    只是听闻过这个恶名远扬的单词,直到有一天我遇到了他

    什么是跨域

    同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。如果两个页面的协议,端口(如果有指定)和主机都相同,则两个页面具有相同的源。我们也可以把它称为“协议/主机/端口 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的组成(统一资源定位符)

    一直以来,自从我接触前端以来,我就在不停的和url打交道,but我之前都是管这个东西叫域名的,
    很是尴尬,
    url中文叫做统一资源定位符,是互联网上一处资源的地址,一个完整的url主要有一下及部分组成

    • 协议部分 ,比较常见的有http https ftp 等
    • 域名部分,比如说www.baidu.com 这一块,也可以用服务器的ip作为域名使用
    • 端口 ,可以不在浏览器中输入,不输入的时候浏览器默认的端口是80
    • 目录部分 ,从域名后边以/开始以/结束,就好比我们电脑里边文件路径
    • 文件名部分,从域名到路径,然后同理后边的是文件命名部分,比如说xxx.html,也可以不写这个文件命名,不写的时候会使用你的服务器设置的默认的文件命名
    • 锚部分 从#开始,#代表页面中的一个位置,右边的字符就是这个位置的标识符,如果页面中有相对应的锚点的或者对应的id的话,浏览器会自动根据锚后边的字符串把可视视图定位到页面的锚点位置
      (这个锚部分,用处非常多,到时候单独整理一盘博客)
    • 参数部分 从? 开始,想必大家之前都见过有些网站的连接后边跟着一些参数,这些参数可以传给服务端,而且这一部分允许有多个参数,可以用&作为分隔符

    跨域的几种常用解决方法

    • 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对象有四个属性

    • data是第一个传的参数

    • origin 表示调用 postMessage 时消息发送方窗口的 origin . 包含了协议,域名和端口

    • source属性 发送消息的窗口对象的引用

    • JsonP跨域

    上边说了script方法 其实这个可以说成是一种,另外补充下比如img link等 都具有跨域访问的能力
    jsonp其实使用这个特性来实现跨域的,在jsonp里边可以定义回调函数,jsonp并不能替代请求,记得有一次微信公众号获取token跨域,jsonp并不能达到相应的效果,感觉jsonp 就是把script标签给封装了一下

    • CORS访问验证

    W3C推荐了一种跨域的访问验证的机制,即CORS(Cross-Origin Resource Sharing 跨源资源共享)。 这种机制让Web应用服务器能支持跨站访问控制,使跨站数据传输更加安全,减轻跨域HTTP请求的风险。

    CORS验证机制需要客户端和服务端协同处理

    现在的各主流的浏览器都会对动态的跨域请求进行特殊的验证处理。验证处理分为简单请求验证处理和预先请求验证处理。

    • 简单请求
      当请求的方法是 GET HEAD POST 且请求头的Content-Type是
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain

    之一的时候,浏览器会直接发送跨域请求,并在请求头中携带访问地址的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了

  • 相关阅读:
    软件开发模式
    my parnter code review
    官僚模式和功能团队模式的优缺点
    思考题
    my code review
    四则运算
    Android Studio下使用Junit框架测试数组和
    SQL2008 存储过程 增删改查例子
    NET 无法显示XML页怎么办
    vs2010 2005 2008 代码前面出现··········取消方法
  • 原文地址:https://www.cnblogs.com/netUserAdd/p/11028853.html
Copyright © 2011-2022 走看看