资讯专栏INFORMATION COLUMN

同源策略和跨域知识点学习

baiy / 679人阅读

摘要:同源策略在这之前需要先熟悉一下这个概念,同源指请求协议相同,主机名相同,端口相同,涉及安全的策略。同源策略主要限制的是不同源之间的交互操作,对于跨域内嵌的资源不受该策略限制。

问题起因是在使用weibo api的时候,发现有一个报错。weibo api是https协议,我本地是模拟的回调域名,然后进行数据通信,本地http协议,于是乎就报错了。出于对postMessage的不是很熟悉,借此机会学习晚上一些自己的知识储备。

api.weibo.com/2/oauth2/authorize?client_id=******&response_type=token&d…ansport=html5&referer=http://www.unofficial.cn/demo/vuejs/demo.html:1 Failed to execute "postMessage" on "DOMWindow": The target origin provided ("https://www.unofficial.cn") does not match the recipient window"s origin ("http://www.unofficial.cn").
同源策略

在这之前需要先熟悉一下这个概念,同源指请求协议相同,主机名相同,端口相同,涉及安全的策略。

    // 例如我的博客地址
    http://www.unofficial.cn/demo/postMessage/pm1.html      同
    http://www.unofficial.cn/demo/vuejs/index.html          同
    https://www.unofficial.cn/demo/postMessage/pm1.html     不同 协议不同
    http://blog.unofficial.cn/demo/postMessage/pm1.html     不同 主机名不同
    http://www.unofficial.cn:8080/demo/postMessage/pm1.html 不同 端口不同
允许跨域写

表单提交,例如我模拟了一个表单提交到我的一个其它站点。

同源策略主要限制的是不同源之间的交互操作,对于跨域内嵌的资源不受该策略限制。

允许跨域嵌入

标签嵌入脚本,语法错误信息只能在同源脚本中捕捉到(?)。

标签嵌入css

标签嵌入图片

标签嵌入多媒体资源

@font-face

载入的任何资源。可以使用x-frame-options消息头来阻止这种形式的交互。

不允许跨域读

需要注意的是,页面内的引入的文件的域并不重要,重要的是加载该文件的页面所在的域。例如说我在博客的首页引入了 //cdn.bootcss.com/jquery/3.1.1/jquery.min.js 的jquery文件,这时 jquery.min.js 的源应该就是我的博客地址 http://www.unofficial.cn 。

iframe
同域可读可写,跨域可读不可写

// 请求地址://www.unofficial.cn/demo/postmessage/pm2.html



// 不同源时使用contentWindow/contentDocument报错
// pm1.html:12 Uncaught DOMException: Failed to read the "contentDocument" property from "HTMLIFrameElement": Blocked a frame with origin "http://www.unofficial.cn" from accessing a cross-origin frame.(…)

同源

iframe外部操作,主要通过contentDocument/contentWindow,iframe内部使用window.parent,如果只是嵌套了一层可以使用window.top,iframe多层嵌套可以使用window.frameElement

    // 外部 -> 内

    var iframe = document.getElementsByTagName("iframe");
    // 举例第一个
    iframe[0].contentDocument.getElementById("test").innerText = 123;

    // 内部 -> 外
    window.parent.getElementById("test").innerText = 123;

跨域

如果需要在跨域的情况下传递参数怎么操作呢?
iframe内部操作,主要通过 location.hash

    // 外部传递一个123给内部
    var src = iframe[0].src;
    iframe[0].src = src.indexOf("#") != -1 ? src.split("#")[0].concat("#", 123) : src.concat("#", 123);
    // 然后内部监测hashChange,自动获取hash值

    // 内部更改hash
    window.location.hash = 123;
    // 但是如何外部如何监控src的变化呢?

ajax

cors

同域可读可写,跨域请求不能检查到 Access-Control-Allow-Origin 的情况下会被拦截。  
// www.unofficial.cn:4000
// 跨域请求
var url = "http://www.unofficial.cn/demo.php";
var params = "lorem=ipsum&name=binny";

var http = new XMLHttpRequest();
http.open("POST", url, true);

http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
    alert(http.responseText);
}
}
http.send(params);
> XMLHttpRequest cannot load http://www.unofficial.cn/demo.php. No "Access-Control-Allow-Origin" header is present on the requested resource. Origin "http://www.unofficial.cn:4000" is therefore not allowed access.

上面错误提示可以设置 `Access-Control-Allow-Origin` ,于是在header中添加设置即可实现跨域请求。  

参数介绍

Access-Control-Allow-Origin
origin参数指定一个允许向该服务器提交请求的URI.对于一个不带有credentials的请求,可以指定为"*",表示允许来自所有域的请求.

Access-Control-Allow-Origin: http://www.unofficial.cn

Access-Control-Allow-Credentials
它的值是一个布尔值,表示是否允许发送Cookie。默认是 true 允许的。 『实际测试没发现,也许是方法还不对吧。』

Access-Control-Expose-Headers
设置浏览器允许访问的服务器的头信息的白名单。如果没有设置白名单的,默认情况下只能获取 Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma的值,没设置返回 null,否则会得到以下提示:

Refused to get unsafe header "X-Powered-By"

例如:

// 服务端设置
Access-Control-Expose-Headers: X-Powered-By

前端可以这样获取到 X-Powered-By 的属性值

    var http = new XMLHttpRequest();

    http.getResponseHeader("X-Powered-By"); // 

Access-Control-Max-Age
设置预请求时间。即是设置 OPTION 的时间。

Access-Control-Allow-Methods
设置允许的请求方法。

jsonp

cors的方式可以发起post请求,或者说其它形式的请求,但是jsonp只能使用get的方式获取数据。



简单说就是定义好回调处理方法,把回调函数的名称传递给后端,后端拿到数据名称后返回会的数据就是对于回调方法的执行。


/**
 * demo.js的内容
 * abc({"abc":"123"});
 */
什么是postMessage

postMessage是window对象的一个属性,widow.postMessage是一个安全的跨源通信协议。当且仅当执行脚本的页面使用相同的协议(通常都是 http)、相同的端口(http默认使用80端口)和相同的 host(两个页面的 document.domain 的值相同)时,才允许不同页面上的脚本互相访问。 window.postMessage 提供了一个可控的机制来安全地绕过这一限制,当其在正确使用的情况下。

iframe的情况下我们可以这样使用,等待页面加载结束时传参数到指定源。

// localhost ① pm1.html页面中存在一个跨域iframe引用



// www.unofficial.cn pm2.html中我们跨域监听 `message` 获取 `postmessage` 传过来的数据。  

window.open的情况下就需要特殊处理一下了

// localhost ② window.open

延迟多长时间执行?页面加载时间是多长,这个不是很好判断,setTimeout需要略估计一个时间,待open的页面加载完成了再postMessage(应该不比完全加载就可以postMessage了)。要不然就是定时器,定时推一次,直接触发事件后使用window.opener取消定时器。

总结

问题基本都是在过程中发现一个学习一个,对于没有太多场景的学习,只能这样慢慢积累。

参考资料

https://developer.mozilla.org...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80815.html

相关文章

  • 同源策略跨域方法

    摘要:同源策略的控制者是浏览器,浏览器可以控制不同域之间的资源的访问或相互操作,但不控制自己对不同域之间的资源的操作和访问。 同源与跨域 一般情况下,禁止一个域从另一个域读取数据,却可以使用某些从其他域拿到的资源。比如说,允许一个域执行、渲染、应用从其他域获取到的脚本、图片、样式;同样,一个域可以展示从其他域获取的内容,比如在frame中显示html文档。网络资源也可以选择性的让其他域来读取...

    魏宪会 评论0 收藏0
  • 同源策略跨域

    摘要:一些技术都默认采取了同源策略,这些技术范围包括但不限于。但是相比较以上的各种场景和绕过同源策略的方法,的跨域请求设置很容易,只需要在目标服务的根目录下 在前端开发的过程中,我们经常遇到跨域的问题,以下的文章将列举一下我在工作中碰到的跨域问题。以及稍稍的探讨一下为什么会有跨域问题的出现,和所谓的同源策略 同源策略 1. 历史 1995 年由 Netscape 公司提出,之后被其他浏览器厂...

    Achilles 评论0 收藏0
  • 同源策略跨域

    摘要:一些技术都默认采取了同源策略,这些技术范围包括但不限于。但是相比较以上的各种场景和绕过同源策略的方法,的跨域请求设置很容易,只需要在目标服务的根目录下 在前端开发的过程中,我们经常遇到跨域的问题,以下的文章将列举一下我在工作中碰到的跨域问题。以及稍稍的探讨一下为什么会有跨域问题的出现,和所谓的同源策略 同源策略 1. 历史 1995 年由 Netscape 公司提出,之后被其他浏览器厂...

    ideaa 评论0 收藏0
  • 同源策略跨域

    摘要:一些技术都默认采取了同源策略,这些技术范围包括但不限于。但是相比较以上的各种场景和绕过同源策略的方法,的跨域请求设置很容易,只需要在目标服务的根目录下 在前端开发的过程中,我们经常遇到跨域的问题,以下的文章将列举一下我在工作中碰到的跨域问题。以及稍稍的探讨一下为什么会有跨域问题的出现,和所谓的同源策略 同源策略 1. 历史 1995 年由 Netscape 公司提出,之后被其他浏览器厂...

    Seay 评论0 收藏0
  • 跨域跨域请求的方法

    摘要:存在跨域的情况网络协议不同,如协议访问协议。域名和域名对应如访问跨域请求资源的方法代理定义和用法代理用于将请求发送给后台服务器,通过服务器来发送请求,然后将请求的结果传递给前端。定义和用法是现代浏览器支持跨域资源请求的一种最常用的方式。 1、什么是跨域? 由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。存在跨域的情况: 网络协议不同,...

    wwq0327 评论0 收藏0

发表评论

0条评论

baiy

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<