zoukankan      html  css  js  c++  java
  • 前端跨域

    同源策略

    同源策略是由Netscape提出来的一种广泛应用至今的安全策略,它规定必须符合域名、端口、协议完全相同的页面之间才能够互相访问对方的数据,包括BOM、后端接口等,所有支持JavaScript的浏览器都遵守同源策略,这也是出现跨域问题的原因。

    一:利用 JSONP 实现跨域调用

    实现原理: <script>元素的src 属性还可以包含来自外部域的JavaScript 文件。

    JSONP 是 JSON 的一种使用模式,可以解决主流浏览器的跨域数据访问问题。其原理是根据 XmlHttpRequest 对象受到同源策略的影响,而 <script> 标签元素却不受同源策略影响,可以加载跨域服务器上的脚本,网页可以从其他来源动态产生 JSON 资料。用 JSONP 获取的不是 JSON 数据,而是可以直接运行的 JavaScript 语句。 

    JSONP协议建立在网页允许跨域加载JavaScript脚本文件的前提下,具体步骤是:

    • 请求发起方在页面添加一个script标签,地址是另一个域的接口地址
    • 请求发起方通过接口地址的URL查询字符串传递参数,包括约定好的回调函数名称(比如callback)
    • 响应方收到请求并且处理数据,生成一段调用回调函数的JavaScript代码并返回
    • script标签加载到JavaScript代码后自动执行回调函数,将返回的数据传递给回调函数作为参数

    比如:

    http://www.domain.com/a.html页面添加一个标签

    <script src=“http://test.domain.com/b.php?callback=fun1&id=1”></script>

    http://test.domain.com/b.php接收请求并生成JavaScript代码返回。

    fun(

      {code: 0,data: 1234}

    );

    下面是一个简单的请求百度接口的jsonp

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>jsonp</title>
    </head>
    <body>
        <div style="text-align: center;">
         <input type="text" id="text" >
     </div>
     <ul id="listBox">
     </ul>
     <script>
      /* JSONP协议建立在网页允许跨域加载JavaScript脚本文件的前提下,具体步骤是:
        请求发起方在页面添加一个script标签,地址是另一个域的接口地址
        请求发起方通过接口地址的URL查询字符串传递参数,包括约定好的回调函数名称(比如callback)
        响应方收到请求并且处理数据,生成一段调用回调函数的JavaScript代码并返回
        script标签加载到JavaScript代码后自动执行回调函数,将返回的数据传递给回调函数作为参数*/
        text.oninput=function(ev){
            if(!scrEle){
                var scrEle = document.createElement("script");
                scrEle.id = "scrEle";
                scrEle.src = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?cb=callback&wd="+ev.target.value//wd为查询参数 cb为回掉函数
                document.getElementsByTagName("head")[0].appendChild(scrEle);
            }else{
              document.body.removeChild(scrEle); 
          }  
      }
      function callback(json) {
         listBox.innerHTML = '';
         for(var i = 0; i < json.s.length; i ++) {
            listBox.innerHTML += '<li>'+json.s[i]+'</li>'
        }
    }
    </script>
    </body>
    </html>

    优点:1使用简单 2 兼容性好 3

    缺点:1它只支持GET请求而不支持POST等其它类型的HTTP请求 2 jsonp在调用失败的时候不会返回各种HTTP状态码。 3 安全性


    二 :使用 CORS 实现跨域调用

    CORS(Cross-Origin Resource Sharing,跨源资源共享)是W3C 的一个工作草案,定义了在必须访问跨源资源时,浏览器与服务器应该如何沟通。CORS 背后的基本思想,就是使用自定义的HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。

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

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

    服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。

    优点:

    • JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
    • 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。

    缺点:

    • 需要服务器的支持
    • JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS)。

    三:图像Ping

    我们知道,一个网页可以从任何网页中加载图像,不用担心跨域不跨域。这也是在线广告跟踪浏览量的主要方式。也可以动态地创图像,使用它们的onload 和onerror 事件处理程序来确定是否接收到了响应。

    动态创建图像经常用于图像Ping。图像Ping 是与服务器进行简单、单向的跨域通信的一种方式。请求的数据是通过查询字符串形式发送的,而响应可以是任意内容,但通常是像素图或204 响应。通过图像Ping,浏览器得不到任何具体的数据,但通过侦听load 和error 事件,它能知道响应是什么时候接收到的。

    来看下面的例子。

    var img = new Image();
    img.onload = img.onerror = function(){
    alert("Done!");
    };
    img.src = "http://www.example.com/test?name=Nicholas";这里创建了一个Image 的实例,然后将onload 和onerror 事件处理程序指定为同一个函数。这样无论是什么响应,只要请求完成,就能得到通知。请求从设置src 属性那一刻开始,而这个例子在请求中发送了一个name 参数。图像Ping 最常用于跟踪用户点击页面或动态广告曝光次数。

    图像Ping 有两个主要的缺点,

    • 一是只能发送GET 请求,
    • 二是无法访问服务器的响应文本。

    因此,图像Ping 只能用于浏览器与服务器间的单向通信。.

    四:使用web socket

    使用web sockets是一种浏览器的API,它的目标是在一个单独的持久连接上提供全双工、双向通信。(同源策略对web sockets不适用)

    web sockets原理:在JS创建了web socket之后,会有一个HTTP请求发送到浏览器以发起连接。取得服务器响应后,建立的连接会使用HTTP升级从HTTP协议交换为web sockt协议。

    只有在支持web socket协议的服务器上才能正常工作。

    var socket = new WebSockt('ws://www.baidu.com');//http->ws; https->wss

    socket.send('hello WebSockt');

    socket.onmessage = function(event){
      var data = event.data;
    }


    五:跨域页面数据通讯

    1:不同主域的页面

    HTML5提供了postMessage/sendMessage等API允许从一个域发送消息到指定的域,另一个域下的网页可以通过onmessage监听消息并且做出处理。跨文档消息传送,有时候简称为XDM,指的是在来自不同域的页面间传递消息。

    postMessage(data,origin)方法接受两个参数

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

    2.origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以建参数设置为"*",这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

    1:http://wowo.yinker.com

    var iframe = document.getElementById('iframe');
          iframe.onload = function() {
              var data = {
                  name: 'aym'
              };
              // 向domain2传送跨域数据
            iframe.contentWindow.postMessage(JSON.stringify(data), 'http://xc.yinker.com/page/aboutUs.do'); 
         }; 
    
          // 接受domain2返回数据 w
          window.addEventListener('message', function(e) { 
              console.log(e.data); 
          }, false); 

    2:http://xc.yinker.com

    window.addEventListener('message', function(event){
      console.log(event.origin)
      if (event.origin == 'http://wowo.yinker.com') {
        console.log(event.data); //name: 'aym'
        window.parent.postMessage("另一个域名发送过来的", 'http://wowo.yinker.com');
      }
    }, false)

    2: 同主域嵌套页面  document.domain + iframe跨域

    修改domain为主域,比如a.domain.com修改为domain.com,即可互相访问浏览器对象模型。

    1.)父窗口:http://wowo.yinker.com/page/aboutUs.do

    <iframe id="iframe" src="http://xc.yinker.com/page/aboutUs.do"></iframe>
    <script>
        document.domain = 'yinker.com';
        var user = 'admin';
      console.log(document.getElementById('iframe').contentWindow.child)//获取子ifarme的变量
    </script>

    2.)子窗口:http://xc.yinker.com/page/aboutUs.do

    <script>
        document.domain = yinker.com';
      var child = "child"
        // 获取父窗口中变量
        coonsole.log(window.parent.user);
    </script>
    
    

    3:不同主域嵌套页面

    修改子页面的iframe的hash值

  • 相关阅读:
    SQL语句在数据库中可以执行在mybatis执行不了
    spring_08aop原理及案例
    spring_07使用spring的特殊bean、完成分散配置
    spring_06装配bean_2
    spring_05装配bean
    spring_03ApplicationContext三种经常用到的实现
    spring_04bean的生命周期
    spring_02工具及接口案例
    深入理解Ribbon之源码解析
    深入理解Feign之源码解析
  • 原文地址:https://www.cnblogs.com/CDtao/p/6904912.html
Copyright © 2011-2022 走看看