zoukankan      html  css  js  c++  java
  • web 通信类

    1、什么是同源策略级限制?

    2、前后端如何通信?

    3、如何创建ajax?

    4、跨域通信的几种方式?

    什么是同源策略限制:

    先解释什么是源,然后再解释

    源:协议,域名,端口  三个有其中一个不一样,就是不同源,

    就是不是同一个源不能操作另外一个源的东西

    主要限制在以下三个方面:

    cookie、localstorage 和indexDB无法读取

    DOM无法获得

    ajax请求不能发送

    前后端如何通信

    Ajax(同源策略限制)  WebSocket(不受同源策略限制)  CORS(支持同源也支持不同源)

    如何创建ajax?

    XMLHttpRequest对象的工作流程

    兼容性处理

    事件触发的条件

    事件的触发顺序

    创建对象xhr ->open() ->send() 

    响应 xhr.onload = function(){}

    /**
    * [json 实现ajax的json]
    * @param {[type]} options [description]
    * @return {[type]} [description]
    */
    util.json = function (options) {
    var opt = {
    url: '',
    type: 'get',
    data: {},
    success: function () {},
    error: function () {},
    };
    util.extend(opt, options);
    if (opt.url) {
    var xhr = XMLHttpRequest
    ? new XMLHttpRequest()
    : new ActiveXObject('Microsoft.XMLHTTP');
    var data = opt.data,
    url = opt.url,
    type = opt.type.toUpperCase(),
    dataArr = [];
    for (var k in data) {
    dataArr.push(k + '=' + data[k]);
    }
    if (type === 'GET') {
    url = url + '?' + dataArr.join('&');
    xhr.open(type, url.replace(/?$/g, ''), true);
    xhr.send();
    }
    if (type === 'POST') {
    xhr.open(type, url, true);
    xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.send(dataArr.join('&'));
    }
    xhr.onload = function () {
    if (xhr.status === 200 || xhr.status === 304) {
    var res;
    if (opt.success && opt.success instanceof Function) {
    res = xhr.responseText;
    if (typeof res ==== 'string') {
    res = JSON.parse(res);
    opt.success.call(xhr, res);
    }
    }
    } else {
    if (opt.error && opt.error instanceof Function) {
    opt.error.call(xhr, res);
    }
    }
    };
    }
    };

    跨域通信的几种方式

    JSONP:img中的src,link的href,script 中的src这三个都不符合同源策略,但是它们都能跨域获取资源,jsonp就是利用script的这个特点来实现跨域获取数据的

    它只支持GET请求而不支持POST等其它类型的HTTP请求

    jsonp是由两部份组成的,回调函数和数据

    Hash: url#后面的就是hash,hash改变,页面不刷新 缺点:另外由于URL大小的限制,支持传递的数据量也不大。

    postMessage:

    优缺点:

     优点:方便,安全,有效的解决了跨域问题

     缺点:万恶的资本主义,ie8+才支持,而且ie8+<ie10只支持iframe的方式。

    WebSocket:是一种网络协议,与http的差异是:http仅当客户端向服务器发送请求的时候,服务器才会向客户端发送信息,而websocket服务器可以主动向客户端发送信息,客户端也可以向服务器主动发送信息。此协议没有同源限制,协议标识符是 ws,加密后的是wss 详细见http://www.ruanyifeng.com/blog/2017/05/websocket.html

    CORS:

    它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制

    CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

    因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

     浏览器发出CROS请求,就是在头信息增加一个origin字段,这个字段用来说明本次请求来自哪个源,服务器会根据这个源绝对是否同意这次请求

    jsonp

        <div class="left" id="left">left</div>
    <div class="right">right</div>
    </section>
    <script type="text/javascript" charset="utf-8">
    document.getElementById('left').onclick = function () {
    var script = document.createElement('script');
    script.src = "https://api.douban.com/v2/book/search?q=javascript&count=1&callback=handleResponse";
    document.body.insertBefore(script,document.body.firstChild)
    }
    function handleResponse(res){
    console.log('res',res)
    }
    </script>

    hash

    原理是利用location.hash来进行传值。

    假设域名a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html传递信息。

    1) cs1.html首先创建自动创建一个隐藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html页面

    2) cs2.html响应请求后再将通过修改cs1.html的hash值来传递数据

    3) 同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一旦有变化则获取获取hash值

    注:由于两个页面不在同一个域下IE、Chrome不允许修改parent.location.hash的值,所以要借助于a.com域名下的一个代理iframe

    代码如下:

    先是a.com下的文件cs1.html文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function startRequest(){
     var ifr = document.createElement('iframe');
     ifr.style.display = 'none';
     document.body.appendChild(ifr);
    }
     
    function checkHash() {
     try {
      var data = location.hash ? location.hash.substring(1) : '';
      if (console.log) {
       console.log('Now the data is '+data);
      }
     } catch(e) {};
    }
    setInterval(checkHash, 2000);

    cnblogs.com域名下的cs2.html:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //模拟一个简单的参数处理操作
    switch(location.hash){
     case '#paramdo':
      callBack();
      break;
     case '#paramset':
      //do something……
      break;
    }
     
    function callBack(){
     try {
      parent.location.hash = 'somedata';
     } catch (e) {
      // ie、chrome的安全机制无法修改parent.location.hash,
      // 所以要利用一个中间的cnblogs域下的代理iframe
      var ifrproxy = document.createElement('iframe');
      ifrproxy.style.display = 'none';
      ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata'; // 注意该文件在"a.com"域下
      document.body.appendChild(ifrproxy);
     }
    }

    a.com下的域名cs3.html

    1
    2
    //因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值
    parent.parent.location.hash = self.location.hash.substring(1);

    // 利用hash,场景是当前页面 A 通过iframe或frame嵌入了跨域的页面 B
    /

    postMessage

    postMessage实现跨域

       语法:window.postMessage(msg,targetOrigin)

        window: 指目标窗口,可能是window.frames属性的成员或者由window.open方法创建的窗口

        message:要发送的消息,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化,在低版本IE中引用json2.js可以实现类似效果

        targetOrigin:“目标域“,包括:协议、主机名、端口号。若指定为”*“,则表示可以传递给任意窗口,指定为”/“,则表示和当前窗口的同源窗口。

        获取postMessage传来的消息:为页面添加onmessage事件

    1 window.addEventListener('message',function(e) {
    2     
    3 }

        onmessage事件接受一个参数e,它是一个event对象。

        e的几个重要属性:

          1、data:postMessage传递过来的msg

          2、发送消息的窗口对象

          3、origin:发送消息窗口的源(协议+主机+端口号)

         来写一个简单的demo:

         http://source.com/source.html用来发送数据:

    1 <iframe id="iframe" src="http://target.com/target.html"></iframe>
    2 <input id="msg" type="text" placeholder="请输入要发送的消息">
    3 <button id="send">发送</button>
    复制代码
    1 window.onload =function() {
    2     document.getElementById('send').onclick = function() {
    3     var msg = document.getElementById('msg').value;
    4     var iframeWindow = document.getElementById('iframe').contentWindow;
    5     iframeWindow.postMessage(msg,"http://target.com/target.html");
    6     }
    7 }
    复制代码

         http://target.com/target.html用来接收数据:  

    1 <div>
    2     <h2>target.html,以下是接收到的消息:</h2>
    3     <section id="msg">
    4         
    5     </section>
    6 </div>
    复制代码
     1 window.onload = function() {
     2 
     3     if(window.addEventListener){
     4         window.addEventListener("message", handleMessage, false);
     5     }
     6     else{
     7         window.attachEvent("onmessage", handleMessage);
     8     }  
     9 
    10     function handleMessage(event) {
    11         event = event || window.event;
    12 
    13         if(event.origin === 'http://source.com') {
    14             document.getElementById('msg').innerHTML = event.data;
    15         }
    16     }
    17 }
    复制代码

    // Websocket【参考资料】http://www.ruanyifeng.com/blog/2017/05/websocket.html

    var ws = new WebSocket('wss://echo.websocket.org');

    ws.onopen = function (evt) {
    console.log('Connection open ...');
    ws.send('Hello WebSockets!');
    };

    ws.onmessage = function (evt) {
    console.log('Received Message: ', evt.data);
    ws.close();
    };

    ws.onclose = function (evt) {
    console.log('Connection closed.');
    };

    // CORS【参考资料】http://www.ruanyifeng.com/blog/2016/04/cors.html
    // url(必选),options(可选)
    fetch('/some/url/', {
    method: 'get',
    }).then(function (response) {

    }).catch(function (err) {
    // 出错了,等价于 then 的第二个参数,但这样更好用更直观
    });

  • 相关阅读:
    Python3之random模块常用方法
    Go语言学习笔记(九)之数组
    Go语言学习笔记之简单的几个排序
    Go语言学习笔记(八)
    Python3之logging模块
    Go语言学习笔记(六)
    123. Best Time to Buy and Sell Stock III(js)
    122. Best Time to Buy and Sell Stock II(js)
    121. Best Time to Buy and Sell Stock(js)
    120. Triangle(js)
  • 原文地址:https://www.cnblogs.com/liangshuang/p/8495449.html
Copyright © 2011-2022 走看看