跨域与同源策略

跨域与同源策略

浏览器同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。

这是一个用于隔离潜在恶意文件的关键的安全机制。如果协议、端口、主机是相同的,则两个页面源相同。下表是相对于http://abc.com/同源检测

URL是否同域原因
http://abc.com/a/协议、端口、主机相同
https://abc.com/不同的协议( https )
http://abc.com:81/不同的端口 ( 81 ),默认端口为80
http://newabc.com/不同的主机 ( news )
http://www.abc.com/域名不同,顶级域名与www子域名不是一个概念

postMessage(HTML5)

语法

otherWindow.postMessage(message, targetOrigin, [transfer]);

// otherWindow 发送窗口,比如iframe的contentWindow
// message 发送信息
// targetOrigin 定哪些窗口能接收到消息事件 "*" 表示无限制
// transfer [可选] 是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

发送端设置Origin

在使用postMessage时需要注意的是,如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是*。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。

例子:3000端口页面向3001端口页面postMessage,配置targetOriginhttp://192.168.31.235:3001

<iframe id="iframe" src="http://192.168.31.235:3001/test"></iframe>
<script type="text/javascript">
  function postMsg(){
    var msg = {psw: '123456'};
    var targetOrigin = "http://192.168.31.235:3001";
    var frame = document.getElementById('iframe');
    frame.contentWindow.postMessage(msg, targetOrigin);
  }
</script>

如果postMessage发送的目标不是配置的targetOrigin,浏览器就会报错,例如targetOrigin配置的是http://192.168.31.235:3001,而iframe的域是http://192.168.31.235:3002

Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('http://192.168.31.235:3002') does not match the recipient window's origin ('http://192.168.31.235:3001').

接收端检测Origin

为了防止恶意站点发送postMessage,接收端同样需要检测Origin

3001端口(与3000跨域)接受来自3000端口的postMessage,判断是否是目标源,如果是继续工作,否则不做处理。

window.addEventListener("message", onReceivedMessage, false);
function onReceivedMessage(event){
    var origin = event.origin || event.originalEvent.origin;
    if(origin === 'http://192.168.31.235:3000'){
            // do something
        }else{
            return;
        }
}

Access-Control-Allow-Origin 授权

通过目标域返回的HTTP头(Access-Control-Allow-Origin)来授权是否允许跨域访问,默认情况下不允许跨域访问。

语法

允许所有站点请求

Access-Control-Allow-Origin: *

允许特定站点请求

Access-Control-Allow-Origin: http://192.168.31.235:3001

浏览器支持

image

流程图

Access-Control-Allow-Origin 跨域请求流程图

image

例子

现在有2个域,端口3000和3001,3000端口页面ajax请求3001端口的服务,毫无疑问,会跨域报错。

$.ajax({
      url:'http://192.168.31.235:3001/doSomething',
      data:{},
      dataType: 'json',
      contentType: 'application/x-www-form-urlencoded',
      success: function(){},
      error: function(){}
});

现在3001 doSomething接口设置Access-Control-Allow-Origin(以express为例)。

res.header("Access-Control-Allow-Origin", "*");
res.send({
    status: '200',
    msg: 'ok'
});

继续请求ajax请求,跨域请求成功。

image

设置*最大的问题是不判断请求来源,意味着所有请求都可以访问。
解决方法是Access-Control-Allow-Origin授权给特定站点,只有特定站点才可访问,避免非授权访问。

res.header("Access-Control-Allow-Origin", "http://192.168.31.235:3000");

image

如果响应头 Access-Control-Allow-Origin设置成http://192.168.31.235:3002域才可以访问接口,继续原来的请求就会跨域报错。

XMLHttpRequest cannot load http://192.168.31.235:3001/doSomething. The 'Access-Control-Allow-Origin' header has a value 'http://192.168.31.235:3002' that is not equal to the supplied origin. Origin 'http://192.168.31.235:3000' is therefore not allowed access.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值