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

    • 前后端通信方式
    • 如何创建Ajax
    • 什么是同源策略?同源策略的目的?非同源的限制范围?
    • 解决跨域的几种方式

    前后端通信的方式:

    • Ajax
    • WebScocket
    • CROS 

    如何创建Ajax

        原理: 通过XMLHttpRequest对象向服务器发送异步请求,从服务器获得数据,然后操作DOM更新数据。XMLHttpRequest对象是ajax的基础

        XMLHttpReques对象的属性有:

        • onreadystatechange每当readyState状态改变时,就会触发该事件 
        • readyState

            该属性存有XMLHttpRequest的状态。从0到4放生变化:

            • 0(请求未初始化):XMLHttpRequest对象还没有完成初始化
            • 1(服务器连接已建立):XMLHttpRequest对象开始发送请求
            • 2(请求已接收):XMLHttpRequest对象请求发送完成
            • 3(请求处理中):XMLHttpRequest对象开始读取服务器的响应,正在解析接收到的内容
            • 4(请求完成,且响应已就绪):XMLHttpRequest对象读取服务器响应结束       
        • status: 从服务器返回的HTTP状态码
        • responseText从服务器返回字符串形式的响应数据
        • responseXML: 从服务器返回 XML 形式的响应数据        

       封装ajax代码如下:

    function ajax(options){
        //默认参数
        var defaults = {
            url: '',
            type: 'GET',
            data:{},
            success: function(){},
            error: function(){}
        };
        //覆盖默认参数
        for(var key in options){
            defaults[key] = options[key];
        }
        if(defaults.url){
            var xmlhttp = XMLHttpRequest? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');//IE6 不支持XMLHttpRequest
            //参数
            var dataArr = [];
            for(var k in data){
                dataArr.push(k + '=' + data[k]);
            }
            if(defaults.type.toUpperCase() === 'GET'){//GET方法
                var url = defaults.url + '?' + dataArr.join('&');
                xmlhttp.open(defaults.type,url,true); 
                xmlhttp.send();  //将请求发送到服务器
            }else if(defaults.type.toUpperCase() === 'POST'){//POST 方法
                xmlhttp.open(defaults.type,defaults.url,true);
                xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                xmlhttp.send(dataArr.join('&'));
            }
            xmlhttp.onreadystatechange = function(){
                if(xmlhttp.readyState == 4 && (xmlhttp.status == 200 || xmlhttp.status == 304)){
                    if(defaults.success && defaults.success instanceof Function){
                        //接收到相应数据
                        var data = xmlhttp.responseText;
                        defaults.success(data);
                    }
                }else{
                    if(defaults.error && defaults.error instanceof Function){
                        defaults.error();
                    }
                }
            }
        }
    }

     调用方式:

    ajax({
        url: '/url',
        type:'POST',
        data:{
            id: 'id1',
            name:'name'
        },
        success: function(data){
            //成功后执行的代码
            console.log('success')
        },
        error: function(status){
            //失败后执行的代码
        }
    });

    同源策略

      1.什么是同源策略

        先了解一下什么是同源,所谓的“同源”指的是三个相同:

        • 协议相同
        • 域名相同
        • 端口相同

         只有这三个都相同才是同源,否则为非同源。

        同源策略:指的是浏览器对不同源的脚本或者文本的访问进行的限制    

      2. 目的

         为了保护用户信息安全,防止恶意的网站窃取数据

      3.限制范围

        非同源之间有如下行为都是受到限制的:

        • cookie、localStorage无法读取
        • DOM 无法获取
        • AJAX 请求不能发送

         这些限制是必要的,但是有时候我们合理的用途也受到了影响。下面将介绍,如何避免上面三种限制

     解决跨域的方案

        为了解决上面三种情况不再受到限制,我们采用了不同跨域的解决方案

      一、Cookie

       我们知道只同源的网页Cookie才能共享。那么怎么才能获取到非同源网站的cookie呢?可以通过设置document.domain来共享cookie

        方案设置document.domain为一级域名

        该方案的适用条件两个网页一级域名相同,只是二级域名不同的情况

        举例说明:

        网页A (http://btp.example.com/a.html)中设置了一个cookie    

    document.cookie = "number=1";

        网页B (http://test.example.com/b.html)中想获取到网页A中设置的cookie,A和B的主域名相同二级域名不同,是非同源的。此时,我们可以设置document.domain 为一级域名exanple.com,即:    

    document.domain = 'example.com';

        这样,在网页B中就可以读取到网页A中设置的cookie了。

    var allCookie = document.cookie; //'number=1'

       二、DOM元素获取

        适用条件: iframe页面,父窗口和子窗口两个页面的一级域名相同,只是二级域名不同的情况

          方案:设置document.domain为一级域名

        举例说明:

        父页面 A (http://btp.example.com/a.html):

    <div id="parent">parent</div>
    <iframe id="iframe" src="http://test.example.com/b.html" height="200" width="200"></iframe>
    <script>
        window.onload = function(){
            var _iframe = document.getElementById('iframe').contentWindow;
            var div = _iframe.document.getElementById('child');
        }
    </script>

        子页面 B(http://test.example.com/b.html):

    <div id="child">child</div>
    <script>
        window.onload = function(){
        var _iframe = window.parent;
        var _div = _iframe.document.getElementById('parent');
    }
    </script>

        由于跨域导致浏览器会报错。只需要设置 在页面那中设置 document.domain = 'example.com’,就可以拿到DOM元素了

      三、通信

        对于主域名相同二级域名不同的情况,我们可以设置document.domain属性来解决跨域通行。那么对于完全不同源的网站,可以使用以下方法来解决:

         1. hash

          方案:把信息放到URL的#号后面,然后通过监听haschange事件

          适用条件:A 通过iframe嵌入(或frame嵌入了跨域的)页面 B

          举例说明:

          父窗口把数据data写到子窗口url的#号后面:     

    <div id="parent">parent</div>
    <iframe id="iframe" src="http://example.com/b.html" height="200" width="200"></iframe>
    <script>
      var B = document.getElementById('iframe').src;

      B.src = B.src + '#' + data;
    </script>

          子窗口监听haschange事件得到通知:

     window.onhaschange = function(){
            var message = window.location.hash;
        }

          子窗口也同样可以把数据传给父窗口

     parent.location.href = parent.location.href + '#' + data

         2. postMessage

          h5为了解决跨域通信问题,引入了跨域通信API,这个API增加了一个window.postMessage方法,该方法允许跨域通信。

          方案:数据通过postMessage方法发送消息,然后通过监听message来获取数据

          适用条件:A 通过iframe嵌入(或frame嵌入了跨域)页面 B

          举例说明:

          父窗口A(http://aa.com/a.html)向子窗口B(http://example.com/b.html)发送消息 : Bwindow.postMessage(message,origin)

    <div id="parent">parent</div>
    <iframe id="iframe" src="http://example.com/b.html" height="200" width="200"></iframe>
    <script>
        window.onload = function(){
            var data ={
                name:'test',
                age:8
            };
            document.getElementById('iframe').contentWindow.postMessage(JSON.stringify(data),'http://example.com'); } </script>

      注: postMessage的写法,postMessage之前是你要通行的window对象(也就是你要向谁通信),上例子中是向子窗口B发送消息。 

      postMessage方法中接收两个参数:

       * 第一个参数:传递的数据(推荐使用字符串格式)

       * 第二个参数:目标窗口的源,协议+主机+端口号。如果设置为“*”,表示可以传递任意窗口

      子窗口B接收数据:

    window.addEventListener('message',function(event){
        console.log(event.source); //发送消息的窗口window对象 A窗口的window
        console.log(event.origin); //发送消息的窗口的源 http://aa.com
        console.log(event.data); //消息内容 {name:'test',age:8};
    },false);

        子窗口通过event.source属性引用父窗口,可以向父窗口发送消息

    window.addEventListener('message',function(event){
       event.source.postMessage('hello',event.origin)
    },false);

      四、AJAX

        AJAX只能发送给同源的网址,否则会报错。解决ajax跨域的方案如下: 

        1.  JSONP(只能发GET请求)

          JSONP基本思想:网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策的限制;服务器收到请求后,将数据放到指定名字的回调函数中传回来

          具体步骤:

            1.动态插入<script>元素,由它向跨源网址发出请求

            2. 该请求的url有一个callback参数,用来指定回调函数的名字,该回调函数需要在页面中定义好。

            3. 服务器收到请求后,会将数据放到指定的回调函数中作为参数返回。

          具体代码实现:

      function createScript(src){
            var script = document.createElement('script');
            script.setAttribute('type','text/javascript');
            script.src = src;
            document.getElementsByTagName('head')[0].appendChild(script);
        };
        window.onload = function(){
            var url = 'http://example.com/ip?callback=foo';
            createScript(url);
        };
        //定义foo函数
        function foo(data){
            console.log('success :' + data);
        }

        服务器收到请求后,会将数据放在回调函数foo的参数位置返回

    foo({success:true,data:[]})

    这样,我们就可以在定义的foo函数中读取到返回的数据了

        2. CORS

          CROS是一种访问机制,全称“跨域资源共享”(Cross-Origin Resource Sharing)。通过在服务器端设置响应头,把跨域的域名添加到Access-Control-Allow-Origin即可

          具体实现 http://www.ruanyifeng.com/blog/2016/04/cors.html

  • 相关阅读:
    Webstorm 2018|2019 官网各大版本破解永久有效
    如何在IDEA 中使用Git
    maven的安装与配置(本地仓库、阿里云镜像设置)
    如何设置使chrome新标签页中打开链接自动跳转到新标签页?
    VMware虚拟机安装Linux系统
    Git安装和使用
    Navicat Premium 12.0.18 安装与激活
    HBuilder mui 报错No 'Access-Control-Allow-Origin' header
    spring+redis 报错 org.springframework.core.serializer.support.DeserializingConverter.<init>(Ljava/lang/ClassLoader;)V
    JAVA 注解
  • 原文地址:https://www.cnblogs.com/yangkangkang/p/8798754.html
Copyright © 2011-2022 走看看