zoukankan      html  css  js  c++  java
  • 实现跨域的5种方法

    1、jsonp

    最常见的一种跨域方式,其背后原理就是利用了script标签不受同源策略的限制,在页面中动态插入了script,script标签的src属性就是后端api接口的地址,并且以get的方式将前端回调处理函数名称告诉后端,后端在响应请求时会将回调返还,并且将数据以参数的形式传递回去。

    前端:

    复制代码
    复制代码
    //http://127.0.0.1:8888/jsonp.html
    var script = document.createElement('script');
    script.src = 'http://127.0.0.1:2333/jsonpHandler?callback=_callback'
    document.body.appendChild(script);      //插入script标签
    //回调处理函数 _callback
    var _callback = function(obj){
          for(key in obj){
            console.log('key: ' + key +' value: ' + obj[key]);
        }
    }
    复制代码
    复制代码

    后端:

    复制代码
    复制代码
    //http://127.0.0.1:2333/jsonpHandler
    app.get('/jsonpHandler', (req,res) => {
      let callback = req.query.callback;
      let obj = {
        type : 'jsonp',
        name : 'weapon-x'
      };
      res.writeHead(200, {"Content-Type": "text/javascript"});
      res.end(callback + '(' + JSON.stringify(obj) + ')');
    })
    复制代码
    复制代码

    2、CORS

    Cross-Origin Resource Sharing(跨域资源共享)是一种允许当前域(origin)的资源(比如html/js/web service)被其他域(origin)的脚本请求访问的机制。
    当使用XMLHttpRequest发送请求时,浏览器如果发现违反了同源策略就会自动加上一个请求头:origin,后端在接受到请求后确定响应后会在Response Headers中加入一个属性:Access-Control-Allow-Origin,值就是发起请求的源地址(http://127.0.0.1:8888),浏览器得到响应会进行判断Access-Control-Allow-Origin的值是否和当前的地址相同,只有匹配成功后才进行响应处理。

    现代浏览器中和移动端都支持CORS(除了opera mini),IE下需要9+

    前端:
    复制代码
    复制代码
    //http://127.0.0.1:8888/cors.html
    var xhr = new XMLHttpRequest();
    xhr.onload = function(data){
      var _data = JSON.parse(data.target.responseText)
      for(key in _data){
        console.log('key: ' + key +' value: ' + _data[key]);
      }
    };
    xhr.open('POST','http://127.0.0.1:2333/cors',true);
    xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    xhr.send();
    复制代码
    复制代码

    后端:

    复制代码
    复制代码
    //http://127.0.0.1:2333/cors
    app.post('/cors',(req,res) => {
      if(req.headers.origin){
        res.writeHead(200,{
          "Content-Type": "text/html; charset=UTF-8",
          "Access-Control-Allow-Origin":'http://127.0.0.1:8888'
        });
        let people = {
          type : 'cors',
          name : 'weapon-x'
        }
        res.end(JSON.stringify(people));
      }
    })
    复制代码
    复制代码

    3、服务器跨域

    在前后端分离的项目中可以借助服务器实现跨域,具体做法是:前端向本地服务器发送请求,本地服务器代替前端再向api服务器接口发送请求进行服务器间通信,本地服务器其实就是个中转站的角色,再将响应的数据返回给前端,下面用node.js做一个示例

    前端:

    复制代码
    复制代码
    //http://127.0.0.1:8888/server
    var xhr = new XMLHttpRequest();
    xhr.onload = function(data){
      var _data = JSON.parse(data.target.responseText)
      for(key in _data){
        console.log('key: ' + key +' value: ' + _data[key]);
      }
    };
    xhr.open('POST','http://127.0.0.1:8888/feXhr',true);  //向本地服务器发送请求   
    xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    xhr.send("url=http://127.0.0.1:2333/beXhr");    //以参数形式告知需要请求的后端接口
    复制代码
    复制代码

    后端:

    复制代码
    复制代码
    //http://127.0.0.1:8888/feXhr
    app.post('/feXhr',(req,res) => {
      let url  = req.body.url;
      superagent.get(url)           //使用superagent想api接口发送请求
          .end(function (err,docs) {
              if(err){
                  console.log(err);
                  return
              }
              res.end(docs.res.text); //返回到前端
          })
    })
    
    //http://127.0.0.1:2333/beXhr
    app.get('/beXhr',(req,res) => {
      let obj = {
        type : 'superagent',
        name : 'weapon-x'
      };
      res.writeHead(200, {"Content-Type": "text/javascript"});
      res.end(JSON.stringify(obj));     //响应
    })
    复制代码
    复制代码

    4、postmessage跨域

    在HTML5中新增了postMessage方法,postMessage可以实现跨文档消息传输(Cross Document Messaging),Internet Explorer 8, Firefox 3, Opera 9, Chrome 3和 Safari 4都支持postMessage。
    该方法可以通过绑定window的message事件来监听发送跨文档消息传输内容。使用postMessage实现跨域的话原理就类似于jsonp,动态插入iframe标签,再从iframe里面拿回数据,私认为用作跨页面通信更加适合

    语法:

    originWindow.postMessage(message, targetOrigin);
    originWindow:要发起请求的窗口引用 
    message: 要发送出去的消息,可以是字符串或者对象 
    targetOrigin: 指定哪些窗口能够收到消息,其值可以是字符串*(表示无限制)或者一个确切的URI
    
    只有目标窗口的协议、主机地址或端口这三者全部匹配才会发送消息。
    • 父窗口 b.com/index.html
      复制代码
      复制代码
      <!DOCTYPE html>
      <html>
      <head>
          <title>Parent window</title>
      </head>
      <body>
      <div>
          <iframe id="child" src="http://a.com/index.html"></iframe>
      </div>
      <input id="p_input" type="txet" value="0">
      <button onclick='p_add()'>parent click to add</button>
      
      <script type="text/javascript">
          window.addEventListener('message',function(e){
              document.getElementById('p_input').value = e.data;
          });
      
          function p_add(){
            var p_input = document.getElementById('p_input');
            var value = +p_input.value+1;
            p_input.value= value;
            window.frames[0].postMessage(value,'http://a.com');
          }
      </script>
      </body>
      </html>
      复制代码
      复制代码
    • 子窗口 a.com/index.html
      复制代码
      复制代码
      <!doctype html>
      <html>
      <head>
          <title>Child window</title>
      </head>
      <body>
        <input id="c_input" type="text" value="0">
        <button onclick='c_add()'>child click to add</button>
      <script type="text/javascript">
          var c_input=document.getElementById('c_input');
      
          window.addEventListener('message', function(e) {
              if(e.source!=window.parent) return;
              var value = +c_input.value+1;
              c_input.value = value;
          });
      
          function c_add(){
              var value = +c_input.value+1;
              c_input.value = value;
              window.parent.postMessage(value,'http://b.com');
          }
      </script>
      </body>
      </html>
      复制代码
      复制代码

    五、修改document.domain跨子域

    ​ 前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域,所以只能跨子域

    ​ 在根域范围内,允许把domain属性的值设置为它的上一级域。例如,在”aaa.xxx.com”域内,可以把domain设置为 “xxx.com” 但不能设置为 “xxx.org” 或者”com”。

    现在存在两个域名aaa.xxx.com和bbb.xxx.com。在aaa下嵌入bbb的页面,由于其document.name不一致,无法在aaa下操作bbb的js。
    
    可以在aaa和bbb下通过js将document.name = 'xxx.com';设置一致,来达到互相访问的作用。
  • 相关阅读:
    Power BI for Office 365(八)共享查询
    Power BI for Office 365(七) Power BI站点
    Power BI for Office 365(六)Power Map简介
    Power BI for Office 365(五)Power View第二部分
    Power BI for Office 365(四)Power View第一部分
    Power BI for Office 365(三)Power Pivot
    Power BI for Office 365(二)Power Query
    java 继承、重载、重写与多态
    Android 热修复方案Tinker(一) Application改造
    阿里最新热修复Sophix与QQ超级补丁和Tinker的实现与总结
  • 原文地址:https://www.cnblogs.com/Bree/p/12009016.html
Copyright © 2011-2022 走看看