美文网首页
跨域的几种方式及原理

跨域的几种方式及原理

作者: 豁啦子 | 来源:发表于2019-01-17 14:37 被阅读0次

    跨域是什么

    同源策略

    • 浏览器出于安全方面的考虑只允许本域下的接口交互,不同源的客户脚本在无明确授权下不能读写对方资源,其中本域是指:
    1. 同协议如都为http;
    2. 同域名,如a.hhh.com和b。haha.com不是同域名;
    3. 同端口,如都为80端口

    跨域实现的几种方式

    JSONP方式

    • 此方式原理是在页面上预先声明一个函数,通过<script>标签没有跨域限制的特性,引入其它域下的数据,因引入的数据浏览器会当作JS文件来执行,所以<script>标签会将预先声明的函数名作为参数传入,而后台接收到后会将数据包裹上这个函数名传回给浏览器,浏览器在接收到数据后把其当作JS文件来执行就会调用此前声明的函数,由此实现目的
    • 演示如下
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>JS Bin</title>
    </head>
    <body>
      <div class='weather'>
        <p>城市</p>
        <p>深圳</p>
        <p>多云</p>
        <button class='change'>其它城市</button>
      </div>
      <script>
        function $(selector){
          return document.querySelector(selector)
        }
        $('.change')addEventListener('click',function(){
          var script = document.createElement('script')
          script.src = 'http://localost:8080/getweather?callback = appendHtml'
          document.head.appendChild(script)
          document.head.removeChild(script)
        })
        function appendHtml(e){
          var html = ''
          for(var i = 0;i<e.length;i++){
            html +='<p>' + e[i] + '</p>'
          }
          $('.weather').innerHTML = html
        }
      </script>
    </body>
    </html>
    

    服务器文件则是:

    var http = require('http');
    var fs = require('fs');
    var path = require('path');
    var url = require('url');
    
    http.createServer(function(req,res){
     var pathObj = url.parse(req.url,true);
      switch (pathObj.pathName){
        case '/getweather':
          var weather = [
            "广州',
            "天气",
            "晴天"
          ]
          res.setHeader('content-type','text/json,charsetutf-8')
          if(pathObj.query.collback){
            res.end(pathObj.query.collback + '(' + JSON.stringify(weather) + ')')
          }else{
            res.end(JSON.stringify(weather))
          }
          break
      }
      default:
      fs.readFile(path.join(__dirname,pathObj.pathName),function(err,data){
        if(err){
          res.end('<h1>404 Not Found</h1>')
        }else{
          res.end(data)
        }
      })
    });
    server.listen(8080)
    

    CORS方式

    • 此方式原理是根据浏览器在发送ajax请求时发现不是同源的情况下会在请求头中加入Origin,我们在服务器若发现此请求头,根据预先允许获得数据的域名判断,允许的域名在返回时数据时会加入一个Access-Contro-Allow-Origin的响应头,浏览器如果发现响应头Origin有值则会拿到数据,如果没有则会直接驳回。所以此方式的ajax请求不会有任何改变,只需服务端写入即可
    • 演示如下
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>JS Bin</title>
      <style>
        
      </style>
    </head>
    <body>
      <div class='weather'>
        <p>城市</p>
        <p>深圳</p>
        <p>多云</p>
        <button class='change'>其它城市</button>
      </div>
      <script>
        function $(selector){
          return document.querySelector(selector)
        }
        $('.change')addEventListener('click',function(){
          var xhr = new XMLHttpRequest()
          xhr.open('GET','locahost:8080',true)
          xhr.send()
          xhr.addEventListener('chick',function(){
            if((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304){
              var data = xhr.responseText
              console.log(data)
            }else{
              console.log('error')
            }
          })
        })
        function appendHtml(e){
          var html = ''
          for(var i = 0;i<e.length;i++){
            html +='<p>' + e[i] + '</p>'
          }
          $('.weather').innerHTML = html
        }
      </script>
    </body>
    </html>
    

    可以看出来上面的html是完全正常的,正常的发送ajax请求。
    服务器端则是

    var http = require('http');
    var fs = require('fs');
    var path = require('path');
    var url = require('url');
    
    http.createServer(function(req,res){
     var pathObj = url.parse(req.url,true);
      switch (pathObj.pathName){
        case '/getweather':
          var weather = [
            "广州',
            "天气",
            "晴天"
          ]
          res.setHeader('Access-Contro-Allow-Origin','http://locahost:8080')      
          res.end(JSON.stringify(weather))
          break
      }
      default:
      fs.readFile(path.join(__dirname,pathObj.pathName),function(err,data){
        if(err){
          res.end('<h1>404 Not Found</h1>')
        }else{
          res.end(data)
        }
      })
    });
    server.listen(8080)
    

    此方式最仅需改动服务端即可实现。是一种较好的实现方式。

    降域方式

    • 此方式原理是利用document.domain = '相同的域名部分'实现有条件的跨域效果,其前提条件就是含有相同的域名,实现如同在本域内之间访问的效果
      -实现演示
    a.html
    
    <iframe src="http://b.liukang.com:8080/b.html" frameborder="0" ></iframe>
    <script>
    //当前url  a.liukang.com
    document.domain=liukang.com
    </script>
    b.html
    
    <script>
    document.domain=liukang.com
    </script>
    

    POST Message方式

    • 实现如下
    a.html
    
    <div class="ct">
        <div class="main">
            <input type="text" placeholder="http://a.jirengu.com:8080/a.html">
        </div>
    
        <iframe src="http://localhost:8080/b.html" frameborder="0" ></iframe>
    
    </div>
    <script>
    //URL: http://a.jirengu.com:8080/a.html
    var oInput=document.querySelector(".main input");
    oInput.addEventListener('input', function(){
        window.frames[0].postMessage(this.value,'*');
    })
    window.addEventListener('message',function(e) {
            oInput.value = e.data
    });
    b.html
    
    <input id="input" type="text"  placeholder="http://b.jirengu.com:8080/b.html">
    <script>
    
    // URL: http://b.jirengu.com:8080/b.html
     var oInput=document.querySelector("#input");
    oInput.addEventListener('input', function(){
        window.parent.postMessage(this.value, '*');
    })
    
    window.addEventListener('message',function(e) {
            oInput.value = e.data
    });
    </script>
    

    相关文章

      网友评论

          本文标题:跨域的几种方式及原理

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