题目原由是在运用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 差别 端口差别
许可跨域写
表单提交,比方我模仿了一个表单提交到我的一个别的站点。
同源战略主要限定的是差别源之间的交互操纵,关于跨域内嵌的资本不受该战略限定。
许可跨域嵌入
<script src=”……”></script> 标签嵌入剧本,语法毛病信息只能在同源剧本中捕捉到(?)。
<link rel=”stylesheet” href=”……”> 标签嵌入css
<img src=”” alt=””> 标签嵌入图片
<video></video> 和 <audio></audio> 标签嵌入多媒体资本
@font-face
<iframe src=”……” frameborder=”0″></iframe> 载入的任何资本。能够运用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
<iframe src="pm2.html" frameborder="0"></iframe>
<iframe src="//blog.unofficial.cn/demo/postmessage/pm2.html" frameborder="0"></iframe>
<script>
window.onload = function() { // 必需守候文档加载完毕才猎取
var iframe = document.getElementsByTagName('iframe');
console.log(iframe[0].contentDocument); // 同源
console.log(iframe[1].contentDocument); // 差别源
}
</script>
// 差别源时运用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-Control
、Content-Language
、Content-Type
、Expires
、Last-Modified
、Pragma
的值,没设置返回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的体式格局猎取数据。
<script>
function abc(data) {
console.log(data);
}abc('{"abc":"123"}');
</script>
<script src="http://www.unofficial.cn/test/demo.php?callback=abc"></script>
简单说就是定义好回调处置惩罚要领,把回调函数的称号通报给后端,后端拿到数据称号后返回会的数据就是关于回调要领的实行。
<script src="http://www.unofficial.cn/test/demo.js"></script>
/**
* demo.js的内容
* abc({"abc":"123"});
*/
什么是postMessage
postMessage是window对象的一个属性,widow.postMessage是一个平安的跨源通信协定。当且仅当实行剧本的页面运用雷同的协定(一般都是 http)、雷同的端口(http默许运用80端口)和雷同的 host(两个页面的 document.domain 的值雷同)时,才许可差别页面上的剧本相互接见。 window.postMessage 供应了一个可控的机制来平安地绕过这一限定,当其在准确运用的情况下。
iframe的情况下我们能够如许运用,守候页面加载完毕时传参数到指定源。
// localhost ① pm1.html页面中存在一个跨域iframe援用
<iframe src="//www.unofficial.com/demo/postMessage/pm2.html" frameborder="0"></iframe>
<script>
window.onload = function() {
window.frames[0].postMessage('some messages', '*'); // * 跨域是牢固的targetOrigin(必需指明协定、主机名、端口) http://www.unofficial.com
}
</script>
// www.unofficial.cn pm2.html中我们跨域监听 `message` 猎取 `postmessage` 传过来的数据。
<script>
window.addEventListener('message', function(event) {
if(event.origin.test('//localhost/')) {
console.log(event.data);
}
})
</script>
window.open的情况下就须要特别处置惩罚一下了
// localhost ② window.open
<script>
function openAPage() {
// 同源的情况下能够推断页面是不是加载完毕
var openPage = window.open('//localhost/demo/postMessage/pm2.html');
openPage.onload = function() {
openPage.postMessage('some messages', '*');
}
// 差别源的情况下,运用setTimeout或许setInterval
var openPage = window.open('//www.unofficial.com/demo/postMessage/pm2.html');
setTimeout(function() {
openPage.postMessage('some messages', '*');
}, 0)
}
</script>
耽误多长时候实行?页面加载时候是多长,这个不是很好推断,setTimeout须要略预计一个时候,待open的页面加载完成了再postMessage(应当不比完整加载就能够postMessage了)。要不然就是定时器,定时推一次,直接触发事宜后运用window.opener作废定时器。
总结
题目基础都是在过程当中发明一个进修一个,关于没有太多场景的进修,只能如许逐步积聚。