跨域--什么是跨域?以及跨域的常用解决方案

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

什么是同源策略?
同源策略/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>
posted @ 2020-10-19 14:08  ashen1999  阅读(180)  评论(0编辑  收藏  举报