Fork me on GitHub

同源策略及前后端(同源/跨域)通信

什么是同源策略和限制?

:= 协议 + 域名 + 端口

同源策略:在MDN中有如下解释:同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。

限制:当源不一样时,就产生了跨域。不是一个源的文档没有权利去操作另一个源的文档。具体表现为:

  • Cookie、LocalStorage、IndexDB 无法读取
  • DOM 无法获得
  • AJAX请求无法发送 前后端如何通信?

  • AJAX(同源)
  • WebSocket(不受同源策略限制)
  • CORS(支持跨域也支持同源通信)

如何创建Ajax

  • XMLHttpRequest
  • 兼容性处理 : windows下为window.ActiveXObject('Microsoft.XMLHTTP')
  • 事件触发条件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // Ajax实现
    var xhr = XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject('Microsoft.XMLHTTP');
    xhr.onreadystatechange = function() {
    if(xhr.readyState == 4) {
    if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
    alert(xhr.responseText);
    } else {
    alert("Request was unsuccessful: " + xhr.status);
    }
    }
    }

    xhr.open("get", "example.txt", true);

    // 如何设置请求头? xhr.setRequestHeader(header, value);
    xhr.setRequestHeader('Content-Type', 'application/json');

    xhr.send(null);

跨域通信的几种方式

  • JSONP
    (1)动态创建一个<script>标签,发送给服务端一个包含回调名callback,并且在本地创建一个与回调名相同的全局函数
    (2)服务端返回数据
    (3)浏览器将返回的数据当成js来执行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    // jsonp实现
    function jsonp(url,func) {

    var _script = document.createElement("script");

    if(url.indexOf("?") === -1){
    script.src = url+"?callback="+func;
    } else {
    script.src = url+"&callback="+func;
    }

    document.body.insertBefore(_script,document.body.firstChild);
    script.onload = script.onreadystatechange = function() {
    // onload
    delete _script;
    script.parentNode.removeChild(_script);
    }
    script.onerror = function() {
    // onerror
    delete _script;
    script.parentNode.removeChild(_script);
    }
    }

    function result(res) {
    console.log(res.name);
    }
  • postMessage:H5中新增的标准,主要用于iframe

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //窗口A(http:A.com)向跨域的窗口B(http://B.com)发送消息
    //A窗口中
    B窗口对象.postMessage('data','http://B.com');
    //在窗口B中监听
    window.addEventListener('message',function(event) {
    console.log(event.origin); // http://A.com
    console.log(event.sourcr); // Awindow
    console.log(event.data); // data
    },false);
  • Hash:页面不刷新也能获取新资源,主要用于iframe

    1
    2
    3
    4
    5
    6
    7
    8
    // 使用场景:当前页面A通过iframe嵌入了跨域的页面B
    // A中伪代码如下
    var B = document.getElementsByTagName('iframe');
    B.src = B.src + '#' + 'data';
    // B中伪代码如下
    window.onhashchange = function() {
    var data = window.location.hash;
    }
  • nginx反向代理:主要使用了nginx.conf内的proxy_pass http://xxx.xxx.xxx,将所有请求代理到该域名,有利有弊。

  • WebSocket:全双工通信方式
    主要原理是:基于HTTP向服务端发送WebSocket请求,服务端许可后返回101,客户端收到101,将协议换成WebSocket,建立连接。

  • CORS:可以理解为支持跨域通信的AJAX
    主要原理是:浏览器发现了有跨域的AJAX请求,就会自动添加一些附加的头部信息(一般为Origin)后发送给服务端,如果服务端允许CORS,则返回Access-Control-Allow-Credentials字段以及其他可选字段,如果没有该字段则说明出错。
    完整原理:阮一峰博客

返回顶部