甚么是布吕马:
应用程序对javascript的相混思路的管制,比如http://a.cn上面的js无法初始化http://b.cn中的js,第三类或统计数据(即使http://a.cn和http://b.cn
是不草同域),因此布吕马就再次出现了.
草同域:单纯的说明是搜索引擎完全相同,路由器完全相同,协定完全相同
为甚么须要布吕马?
在最一已经开始,他们晓得了,布吕马只存有于应用程序端。而应用程序为 web 提供更多出访出口处。他们在能应用程序内关上许多页面。便是这种的对外开放型态,因此他们须要对他略有管制。就比如说陈家大了,甚么鸟都有,他们须要有两个标准化的规范化来展开签订合同就可以保证那个可靠性。
列出的方式挺多的,在复试的这时候,多于提问1-2个就能了,能看一看前面的单纯版的标准答案。
1.相混思路如下表所示:
当心三点:第三,假如是协定和路由器导致的布吕马难题“后台”是束手无策的,第三:在布吕马难题上,域实际上是透过“URL的第三部”来辨识而无法去试著推论完全相同的ip门牌号相关联着两个域或三个域与否在同一ip上。“URL的第三部”指window.location.protocol +window.location.host,也能认知为“Domains, protocols and ports must match”。2. 后端化解布吕马难题
一、 document.domain + iframe (多于在主域完全相同的这时候就可以采用该方式)
1) 在http://www.a.com/a.html中:
document.domain = a.com;
var ifr = document.createElement(iframe);
ifr.src = http://www.script.a.com/b.html;ifr.display = none;
document.body.appendChild(ifr);
ifr.onload = function(){
var doc = ifr.contentDocument || ifr.contentWindow.document;
//在这里操作doc,也是b.html
ifr.onload = null;
};
2、在http://www.script.a.com/b.html中:
document.domain = a.com;
二、 动态创建script
那个没甚么好说的,即使script标签不受相混思路的管制。
function loadScript(url, func) {
var head = document.head || document.getElementByTagName(head)[0];
var script = document.createElement(script);
script.src = url;
script.onload = script.onreadystatechange = function(){
if(!this.readyState || this.readyState==loaded || this.readyState==complete){
func();
script.onload = script.onreadystatechange = null;
}
};
head.insertBefore(script, 0);
}
window.baidu = {
sug: function(data){
console.log(data);
}
}
loadScript(http://suggestion.baidu.com/su?wd=w,function(){console.log(loaded)});//他们请求的内容在哪里?
//他们能在chorme调试面板的source中看到script引入的内容
三、 location.hash + iframe
原理是利用location.hash来展开传值。
假设搜索引擎http://a.com下的文件cs1.html要和http://cnblogs.com搜索引擎下的cs2.html传递信息。
1) cs1.html首先创建自动创建两个隐藏的iframe,iframe的src指向http://cnblogs.com搜索引擎下的cs2.html网页
2) cs2.html响应请求后再将透过修改cs1.html的hash值来传递统计数据
ash值
注:由于三个网页不在同一域下IE、Chrome不允许修改parent.location.hash的值,因此要借助于http://a.com搜索引擎下的两个代理iframe
代码如下表所示:
先是http://a.com下的文件cs1.html文件:
function startRequest(){
var ifr = document.createElement(iframe);
ifr.style.display = none;
ifr.src = http://www.cnblogs.com/lab/cscript/cs2.html#paramdo;
document.body.appendChild(ifr);
}
function checkHash() {
try {
var data = location.hash ? location.hash.substring(1) : ;
if (console.log) {
console.log(Now the data is +data);
}
} catch(e) {};
}
setInterval(checkHash, 2000);
http://cnblogs.com搜索引擎下的cs2.html:
//模拟两个单纯的参数处理操作switch(location.hash){
case #paramdo:
callBack();
break;
case #paramset:
//do something……
break;
}
function callBack(){
try {
parent.location.hash = somedata;
} catch (e) {
// ie、chrome的安全机制无法修改parent.location.hash, // 因此要利用两个中间的cnblogs域下的代理iframe
var ifrproxy = document.createElement(iframe);
ifrproxy.style.display = none;
ifrproxy.src = http://a.com/test/cscript/cs3.html#somedata; // 注意该文件在”a.com”域下
document.body.appendChild(ifrproxy);
}
}
http://a.com下的搜索引擎cs3.html
//即使parent.parent和自身属于同一域,因此能改变其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1);
四: window.name + iframe
window.name 的美妙之处:name 值在相同的网页(甚至不草同搜索引擎)加载后依旧存有,并且能支持非常长的 name 值(2MB)。
1) 创建http://a.com/cs1.html
2) 创建http://a.com/proxy.html,并加入如下表所示代码
<head>
<script>
function proxy(url, func){
var isFirst = true,
ifr = document.createElement(iframe),
loadFunc = function(){
if(isFirst){
ifr.contentWindow.location = http://a.com/cs1.html;
isFirst = false;
}else{
func(ifr.contentWindow.name);
ifr.contentWindow.close();
document.body.removeChild(ifr);
ifr.src = ;
ifr = null;
}
};
ifr.src = url;
ifr.style.display = none;
if(ifr.attachEvent) ifr.attachEvent(onload, loadFunc);
else ifr.onload = loadFunc;
document.body.appendChild(iframe);
}
</script>
</head>
<body>
<script>
proxy(http://www.baidu.com/, function(data){ console.log(data);
});
</script>
</body>
3 在http://b.com/cs1.html中包含:
<script>
window.name = 要传送的内容;
</script>
五: postMessage(HTML5中的XMLHttpRequest Level 2中的API)
1) http://a.com/index.html中的代码:
<iframe id=“ifr” src=“b.com/index.html”></iframe>
<script type=“text/javascript”>
window.onload = function() {
var ifr = document.getElementById(ifr);
var targetOrigin = http://b.com; // 若写成http://b.com/c/proxy.html效果一样 // 若写成http://c.com就无法执行postMessage了
ifr.contentWindow.postMessage(I was there!, targetOrigin);
};
</script>
2) http://b.com/index.html中的代码:
<script type=“text/javascript”>
window.addEventListener(message, function(event){
if (event.origin == http://a.com) {
alert(event.data); // 弹出”I was there!” alert(event.source); // 对a.com、index.html中window第三类的引用
// 但由于相混思路,这里event.source无法出访window第三类 }
}, false);
</script>
六:CORS【那个我也不晓得哈】
CORS背后的思想,是采用自定义的HTTP头部让应用程序与服务器展开沟通,从而决定请求或响应是应该成功,还是应该失败。
IE中对CORS的实现是xdr
var xdr = new XDomainRequest();
xdr.onload = function(){
console.log(xdr.responseText);
}
xdr.open(get, http://www.baidu.com);
……
xdr.send(null);
其它应用程序中的实现就在xhr中
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState == 4){
if(xhr.status >= 200 && xhr.status < 304 || xhr.status == 304){
console.log(xhr.responseText);
}
}
}
xhr.open(get, http://www.baidu.com);
……
xhr.send(null);
实现跨应用程序的CORS
function createCORS(method, url){
var xhr = new XMLHttpRequest();
if(withCredentials in xhr){
xhr.open(method, url, true);
}else if(typeof XDomainRequest != undefined){
var xhr = new XDomainRequest();
xhr.open(method, url);
}else{
xhr = null;
}
return xhr;
}
var request = createCORS(get, http://www.baidu.com);
if(request){
request.onload = function(){
……
};
request.send();
}
七:JSONP
JSONP包含两部分:回调函数和统计数据。
回调函数是当响应到来时要放在当前网页被初始化的函数。
统计数据是传入回调函数中的json统计数据,也是回调函数的参数了。
function handleResponse(response){
console.log(The responsed data is: +response.data);
}
var script = document.createElement(script);
script.src = http://www.baidu.com/json/?callback=handleResponse;document.body.insertBefore(script, document.body.firstChild);
/*handleResonse({“data”: “zhe”})*/
//原理如下表所示://当他们透过script标签请求时
//后台就会根据相应的参数(json,handleResponse)
//来生成相应的json统计数据(handleResponse({“data”: “zhe”}))//最后那个返回的json统计数据(代码)就会被放在当前js文件中被执行
//至此布吕马通信完成
jsonp虽然很单纯,但是有如下表所示缺点:
1)安全难题(请求代码中可能存有安全隐患)
2)要确定jsonp请求与否失败并不容易
八: web sockets
web sockets是一种应用程序的API,它的目标是在两个单独的持久连接上提供更多全双工、双向通信。(相混思路对web sockets不适用)
web sockets原理:在JS创建了web socket之后,会有两个HTTP请求发送到应用程序以发起连接。取得服务器响应后,建立的连接会采用HTTP升级从HTTP协定交换为web sockt协定。
多于在支持web socket协定的服务器上就可以正常工作。
var socket = new WebSockt(ws://www.baidu.com);//http->ws; https->wss
socket.send(hello WebSockt);
socket.onmessage = function(event){
var data = event.data;
}
参考于:
作者:PheonixHkbxoic
链接:https://www.cnblogs.com/PheonixHkbxoic/p/5760838.html
总结
布吕马难题在目前后端分离的架构中普遍存有,本文所介绍的这几种计划虽然都能够化解布吕马难题,但其实各有优劣。比如说Jsonp方式实现起来较为单纯,但只支持GET请求方式,在原生JavaScript脚本中采用方便,但是当利用了如Vue.js这种MVVM框架时就有些难以施展了。反向代理的方式无需改动后端代码,但是对整个系统而言可移植性较差,CORS方式须要后端来积极配合后端实现布吕马。总之,没有技术银弹,他们要在实际情形中比较分析,选择最合适的计划。