zoukankan      html  css  js  c++  java
  • 跨域--什么是跨域?以及跨域的常用解决方案

    我们通常所说的跨域,就是指被同源策略限制了的请求场景。

    什么是同源策略?
    同源策略/SOP(Same origin policy)是一种约定,所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

    常用解决方案

    jsonp

    通过动态生成script,设置src为请求的跨域地址,并在其中拼接回调函数。跨域地址收到请求后,返回一个对该回调函数的调用。从而达到数据通信的实现。
    缺点:只支持get请求。

    CORS

    对于普通请求,只需服务端设置Access-Control-Allow-Origin即可;如果需要携带cookie,则前端需要设置withCredentials

    postMessage

    postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
    a.) 页面和其打开的新窗口的数据传递
    b.) 多窗口之间消息传递
    c.) 页面与嵌套的iframe消息传递
    d.) 上面三个场景的跨域数据传递

    语法: otherWindow.postMessage(message, targetOrigin, [transfer]);
    message: 传输的数据等
    otherWindow: 一个目标窗口的引用
    a.) 通过window.open()返回值
    b.) 通过iframe的contentWindow属性
    targetOrigin: 用来标识哪些窗口可以接受到消息。可以通过'*'配置为任何窗口。但为了安全性考虑,最好进行精准设置一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。
    transfer: 是一串和message一起传递的数据,但是所有权会转到目标窗口。

    用法如下:

    var bWindow = window.open(...b details...)
    var data = {name : 'ashen' ,age : 20}
    bWindow.postMessage(data, 'http://b.org')
    

    在bWindow中

    window.addEventListener('message', receiveMessage, false)
    function receiveMessage(event)
    {
      // 我们能信任信息来源吗?
      if (event.origin !== "http://example.com:8080")
        return;
    
      // event.source 就当前的来源页面
      // event.data 是 "{name : 'ashen' ,age : 20}"
    
      // 假设你已经验证了所受到信息的origin (任何时候你都应该这样做), 一个很方便的方式就是把event.source
      // 作为回信的对象,并且把event.origin作为targetOrigin
      event.source.postMessage("hi there yourself!  the secret response " +
                               "is: rheeeeet!",
                               event.origin);
    }
    
    

    nginx代理

    配置代理服务器,在前端看来并非跨域
    主要通过设置proxy_pass属性,为跨域地址

    WebSocket协议跨域

    websocket实现客户端和服务端的全双工通信,支持跨域

    document.domain + iframe跨域

    通过window.domain设置页面的基础主域相同
    只能处理主域相同子域不同的情况

    location.hash + iframe

    例如需要实现A域的a.html到B域的b.html的跨域。则需要借助同为A域的c.html页面。利用hash值可单向传递的特性实现,如下:

    // a.html
    <iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
    <script>
            setTimeout(function(){
                iframe.src = iframe.src + '#user=admin'
            }, 1000)
    
            function onCallback(res){
                alert('data from c.html ---->' + res)
            }
    </script>
    
    <iframe src="http://www.domain1.com/c.html" style="display: none;"></iframe>
    <script>
            window.onhashchange = function(){
                iframe.src = iframe.src + location.hash
            }
    </script>
    
    <iframe src="http://www.domain2.com/c.html" style="display: none"></iframe>
    <script>
          window.onhashchange = function () {
            window.parent.parent.onCallback(
              "hello" + location.hash.replace("#user=", "")
            );
          };
    </script>
    
  • 相关阅读:
    JAVA复习笔记之GC部分
    elasticsearch学习笔记--原理介绍
    JavaScript--Array数组jion方法使用
    MyBatis探究-----缓存机制详解
    C#---- Winform控件PictureBox详解
    Mybatis探究-----一对一、一对多关联查询
    C#-----CancellationTokenSource取消线程
    MyBatis探究-----接口类映射XML文件中符号$和#的区别
    C#-----定时器的几种实现
    eclipse如何在不联网的情况下引入dtd约束文件
  • 原文地址:https://www.cnblogs.com/ashen1999/p/13839978.html
Copyright © 2011-2022 走看看