进阶13

作者: 安石0 | 来源:发表于2017-06-20 17:13 被阅读0次

    题目1: 什么是同源策略

    同源策略,它是由Netscape提出的一个著名的安全策略
    浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。
    如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
    现在所有支持JavaScript 的浏览器都会使用这个策略。
    所谓同源是指,域名,协议,端口相同。
    IE 例外
    当涉及到同源策略时,Internet Explorer有两个主要的例外
    授信范围(Trust Zones):两个相互之间高度互信的域名,如公司域名(corporate domains),不遵守同源策略的限制。
    端口:IE未将端口号加入到同源策略的组成部分之中,因此 http://company.com:81/index.htmlhttp://company.com/index.html 属于同源并且不受任何限制。

    题目2: 什么是跨域?跨域有几种实现形式

    跨域就是在不同源的接口进行交互
    跨域的实现形式有四种:
    jsonp
    cors
    降域
    postMessage
    详细见题目5

    题目3: JSONP 的原理是什么

    JSONP
    html中script标签可以引入其他域下的js,比如引入线上的jquery库。利用这个特性,可实现跨域访问接口。需要后端支持
    echo $cb . '&&' . $cb . '(' . json_encode($ret) . ')';

    定义数据处理函数_fun
    创建script标签,src的地址执行后端接口,最后加个参数callback=_fun
    服务端在收到请求后,解析参数,计算返还数据,输出 fun(data) 字符串。
    fun(data)会放到script标签做为js执行。此时会调用fun函数,将data做为参数。

    题目4: CORS是什么

    CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 ajax 跨域请求资源的方式,支持现代浏览器,IE支持10以上。 实现方式很简单,当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。所以 CORS 的表象是让你觉得它与同源的 ajax 请求没啥区别,代码完全一样。

    题目5: 根据视频里的讲解演示三种以上跨域的解决方式 ,

    本题模拟跨域,在谷歌浏览器上模拟,设置两个服务器的域名为http://127.0.0.1:2000和http://127.0.0.1:8080,8080向2000端口下的域请求数据
    方法1:jsonp

    <html>
      <head>
        <meta charset="utf-8" />
        <title></title>
      </head>
      <body>
        <div class="container">
          <div class="news">
            <li>中二少时诵诗书</li>
            <li>双男力争会师决赛</li>
            <li>女排死磕巴西</li>
          </div>
          <button id="change">换一组</button>
        </div>
        <script type="text/javascript">
          function $(x){
            return document.querySelector(x)
          }
          $('#change').addEventListener('click',function(){
            var script=document.createElement('script');
            script.src='http://127.0.0.1:2000/page1.json?callback=appendHtml'
            document.head.appendChild(script);
            
          })
        
          function appendHtml(data){
            var html = '';
            for(var i=0; i< data.length; i++){
                html += '<li>'+data[i]+'</li>'
            }
            console.log(html)
            $('.news').innerHTML = html;
        
          }
        
          
        </script>
      </body>
    </html>
    
    
    

    router.js部分

    
    app.get('/page1.json',function(req,res){
      var news=[
      'aaaaaaaa',
      'bbbbbbbb',
      'cccccccc',
      'ddddddddd',
      'eeeeeeeee',
      'fffffffff',
      'ggggggggg'
      ]
      var data=[];
      for(var i=0;i<3;i++){
        var index=parseInt(Math.random()*news.length);
        data.push(news[index]);
        news.splice(index,1)
      }
      
      
      var cb=req.query.callback;
      console.log(cb)
      if(cb){
        res.send(cb+'('+JSON.stringify(data)+')');
      }else{
        res.send(data)
        console.log(data)
      }
      //res.header("Access-Control-Allow-Origin",'*')
      
    })
    
    

    结果如图


    json1.png jsonp2.png
    方法2:cors
    修改一下代码,改成向2000端口发送ajax请求
       $('#change').addEventListener('click',function(){
          /*  var script=document.createElement('script');
            script.src='http://127.0.0.1:2000/page1.json?callback=appendHtml'
            document.head.appendChild(script);
            */
           var xhr=new XMLHttpRequest;
           xhr.onload=function(){
            appendHtml(xhr.response)
           }
           xhr.open('GET','http://127.0.0.1:2000/page1.json',true)
         xhr.send();
          })
    

    得到的结果如图

    cors.png

    现在我在2000端口的服务器上给8080端口的域授权

    
    app.get('/page1.json',function(req,res){
      var news=[
      '啊啊啊啊啊啊a',
      '反反复复付付付付',
      'cの额鹅鹅鹅',
      'd啛啛喳喳',
      '少时诵诗书',
      'f啦啦啦啦绿',
      '世世代代发我'
      ]
      var data=[];
      for(var i=0;i<3;i++){
        var index=parseInt(Math.random()*news.length);
        data.push(news[index]);
        news.splice(index,1)
      }
      
      
      /*var cb=req.query.callback;
      console.log(cb)
      if(cb){
        res.send(cb+'('+JSON.stringify(data)+')');
      }else{
        res.send(data)
        console.log(data)
      }*/
    res.header("Access-Control-Allow-Origin","http://127.0.0.1:8080")
      res.send(data)
    })
    

    得到的结果如图

    cors2.png
    cors.png

    这样就实现了跨域
    方法3postMessege
    window.postMessage()方法可以安全地实现跨源通信。通常,当且仅当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机(模数 Document.domain
    由两个页面设置为相同的值)。 window.postMessage()方法提供了一种受控机制,以便在正确使用时以安全的方式规避此限制。
    window.postMessage()方法被调用时,会在所有页面脚本执行完毕之后(e.g., 在该方法之后设置的事件、之前设置的timeout 事件,etc.)向目标窗口派发一个 MessageEvent
    ** 消息。 该MessageEvent
    消息有四个属性需要注意: message 属性表示该message 的类型; data 属性为 window.postMessage 的第一个参数;origin 属性表示调用window.postMessage()方法时调用页面的当前状态; source 属性记录调用 window.postMessage()方法的窗口信息。
    postMessage的用法为:otherWindow.postMessage(message, targetOrigin, [transfer]);
    第一个参数为:我要发送的data,
    第二个参数为:通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"
    "(表示无限制)或者一个URI,在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;例如,当用postMessage传送密码时,这个参数就显得尤为重要,必须保证它的值与这条包含密码的信息的预期接受者的orign属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是
    。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。
    第三个参数为:Transfer,可选的参数,是一串和message 同时传递的 Transferable
    对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

    post1.png

    如图 在index设置两个frame元素
    index代码

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title></title>
        </head>
        <body>
            <iframe src="1.html" width="300px" height="300px"></iframe>
            <iframe src="2.html" width="300px" height="300px"></iframe>
            
        </body>
    </html>
    
    

    frames[0]代码

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title></title>
        </head>
        <body>
            
            <input  id="i1" value="" placeholder="1-input"/>
            <script type="text/javascript">
            function $(x){
                return document.querySelector(x)
            }
            $('#i1').addEventListener('input',function(){
                //console.log('this.input.value:'+this.value);
            
                window.parent.frames[1].postMessage(this.value,'*');
    //                  给本页面父节点的frame[1]发送消息
                    //console.log(window.frames[0].postMessage);
            })
    //接受发送的消息,因上面没有指定给自己传输,所以收不到上面的消息
        window.addEventListener('message',function(e){
                $('#i1').value=e.data;
                //console.log('e.data:'+e.data)
            })
        
            </script>
        </body>
    </html>
    
    

    frame[1]

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title></title>
        </head>
        <body>
            <input  id="i2" value="" placeholder="2-input"/>
            <script type="text/javascript">
    
            function $(x){
                return document.querySelector(x)
            }
        
            $('#i2').addEventListener('input',function(){
                //console.log('this.input.value:'+this.value);
                window.parent.frames[0].postMessage(this.value,'*')
    //   给本页面父节点的frame[1]发送消息
            })
            //接受发送的消息,因上面没有指定给自己传输,所以收不到上面的消息
            window.addEventListener('message',function(e){
                $('#i2').value=e.data;
                
            })
            </script>
        </body>
    </html>
    
    

    相关文章

      网友评论

          本文标题:进阶13

          本文链接:https://www.haomeiwen.com/subject/llzoqxtx.html