|
当然,“近乎完美”仅僅是个人观点,dan如下所述,它確實簡单而頗有xiao益!
一直在寻求一种自己满意的 JS 跨域方式(这li是指任意跨域),曾经了解过:
即时插入 script 元素的方式,会让腳本立即執行,不安quan,并且需要与跨域的远端做hao约定——比如变量名。细節较为繁琐。
xie iframe 的 location.hash 的方式,huidao致历史记录的产生,且数據量有限,同时,因为 URL 的内容可視,既不hao看也容易泄露信息。
用代理? 虽然算是最“正宗”的完整跨域方案,但太麻烦了點——首先得有代理,Ru果量大De话,代理的負担會很重,会导致“瓶颈”制约。
利用 Flash 跨域,bu在考虑之列——复杂了些,并且那不算是 JS 跨域。
無意中看到一篇文章《使用 window.name jie决跨域問題》……豁然开朗! 俺的問题終于解jue了。
对那个實现小改了一xia,加了瀏览器本地she置 Window.name 的功neng,实現瀏覽器“本地”异域数据的传递(Ru从瀏览器窗口A传递shu据到窗口B,仅在本地进xing,且两ge域不同)——zhe会产生一个很蛙王的应用(下一篇文章《普通 http 网络下shu据的安全傳输》jiang详细shuo明,本文后有少量提及)。感谢网络! 也感謝愿意分享的技術达人!
xia面贴出俺的dai码,ye分享一xia,呵呵……
(zhu意:本de需要创建一个名為 proxy.HTML 的kong文件)
javascript代碼
(function() {
var _isIE = (
navigator.appName == "Microsoft Internet Explorer"
);
var _removeNode = _isIE ? function() {
var d;
return function(n) {
if(n && n.tagName != 'BODY') {
d = d || document.createElement('div');
d.appendChild(n);
d.innerHTML = '';
}
}
}() : function(n) {
if(n && n.parentNode && n.tagName != 'BODY') {
n.parentNode.removeChild(n);
}
};
/* [ Request by window.name ]
* ****************************************************************************
借助 Window.name 实现 Js 的跨域访问。
1、 url 向外传值, callback chu理返回结果。
2、 返回页面中 JS 对 window.name 赋值。
返回页
<script language="JavaScript">
window.name = ... // 支chi JSON 字符串,可达~2MB
</script>
若需同时进行多个請求,hui調函数应是不同的函shu实例。
iframe 的自由载入形成了異步机制。
*/
wnRequest = {
_doc: document,
_proxyUrl: 'proxy.html'
};
wnRequest.send = function( url, callback )
{
if(! url || typeof url !== 'string') {
return;
}
url += (url.indexOf('?') > 0 ? '&' : '?') + 'windowname=get';
var frame = this._doc.createElement('iframe');
frame._state = 0;
this._doc.body.appendChild(frame);
frame.style.display = 'none';
(function( el, type, fn ) {
if (_isIE) {
el.attachEvent('on' + type, fn);
} else {
el.addEventListener(type, fn, false);
}
})(frame, 'load', function() {
if(frame._state == 1) {
_getData(frame, callback);
} else if(frame._state == 0) {
frame._state = 1;
//frame.contentWindow.location = wnRequest._proxyUrl;
frame.contentWindow.location.replace(wnRequest._proxyUrl);
}
});
frame.src = url;
};
//
// 設置异域 Js 可訪问的ben地数据,客户端直接站间转递数据
// 注:
// ji浏览器直接jiang数据轉递给另yi个域De窗口,数据不shang网。
// 返hui页dai码:
// <script type="text/javascript">
// if (window.name) {
// //... 處理 name 值
// window.name = null;
// }
// // 升为顶级窗口,完成数据转递
// try {
// top.location.hostname;
// if (top.location.hostname != window.location.hostname) {
// top.location.href =window.location.href;
// }
// } catch(e) {
// top.location.href = window.location.href;
// }
// </script>
//
//
wnRequest.setname = function( name, url ) {
if(! url || typeof url !== 'string') {
return;
}
url += (url.indexOf('?') > 0 ? '&' : '?') + 'windowname=loc';
var frame = this._doc.createElement('iframe');
frame._count = 0;
this._doc.body.appendChild(frame);
frame.style.display = 'none';
if (_isIE) {
frame.name = name;
} else {
frame.contentWindow.name = name;
}
frame.src = url;
};
//
// 私用辅助
//
var _clear = function(frame) {
try {
frame.contentWindow.document.write('');
frame.contentWindow.close();
_removeNode(frame);
} catch(e) {}
}
var _getData = function(frame, callback) {
try {
var da = frame.contentWindow.name;
} catch(e) {}
_clear(frame);
if(callback && typeof callback === 'function') {
callback(da);
}
}
})();
(function() {
var _isIE = (
navigator.appName == "Microsoft Internet Explorer"
);
var _removeNode = _isIE ? function() {
var d;
return function(n) {
if(n && n.tagName != 'BODY') {
d = d || document.createElement('div');
d.appendChild(n);
d.innerHTML = '';
}
}
}() : function(n) {
if(n && n.parentNode && n.tagName != 'BODY') {
n.parentNode.removeChild(n);
}
};
/* [ Request by window.name ]
* ****************************************************************************
借zhu Window.name 實现 Js 的跨域访问。
1、 url 向外传值, callback 处理返回结果。
2、 返回頁面中 JS 对 window.name 赋值。
返回頁
<script language="JavaScript">
window.name = ... // 支持 JSON 字符串,可达~2MB
</script>
ruo需同时进行多ge请求,回调函數应是不同的函数实例。
iframe 的自you载入形成了異步机制。
*/
wnRequest = {
_doc: document,
_proxyUrl: 'proxy.html'
};
wnRequest.send = function( url, callback )
{
if(! url || typeof url !== 'string') {
return;
}
url += (url.indexOf('?') > 0 ? '&' : '?') + 'windowname=get';
var frame = this._doc.createElement('iframe');
frame._state = 0;
this._doc.body.appendChild(frame);
frame.style.display = 'none';
(function( el, type, fn ) {
if (_isIE) {
el.attachEvent('on' + type, fn);
} else {
el.addEventListener(type, fn, false);
}
})(frame, 'load', function() {
if(frame._state == 1) {
_getData(frame, callback);
} else if(frame._state == 0) {
frame._state = 1;
//frame.contentWindow.location = wnRequest._proxyUrl;
frame.contentWindow.location.replace(wnRequest._proxyUrl);
}
});
frame.src = url;
};
//1
// 設置异域 Js 可訪问的本地数据,客户端直接站间转遞数据
// 注:
// 即浏览器直jie将数据转遞给另一个域的窗口,数据不上网。
// 返回頁代码:
// <script type="text/javascript">
// if (window.name) {
// //... 处理 name 值
// window.name = null;
// }
// // 升為顶级窗口,wan成数据转递
// try {
// top.location.hostname;
// if (top.location.hostname != window.location.hostname) {
// top.location.href =window.location.href;
// }
// } catch(e) {
// top.location.href = window.location.href;
// }
// </script>
//
//
wnRequest.setname = function( name, url ) {
if(! url || typeof url !== 'string') {
return;
}
url += (url.indexOf('?') > 0 ? '&' : '?') + 'windowname=loc';
var frame = this._doc.createElement('iframe');
frame._count = 0;
this._doc.body.appendChild(frame);
frame.style.display = 'none';
if (_isIE) {
frame.name = name;
} else {
frame.contentWindow.name = name;
}
frame.src = url;
};
//
// 私用辅助
//
var _clear = function(frame) {
try {
frame.contentWindow.document.write('');
frame.contentWindow.close();
_removeNode(frame);
} catch(e) {}
}
var _getData = function(frame, callback) {
try {
var da = frame.contentWindow.name;
} catch(e) {}
_clear(frame);
if(callback && typeof callback === 'function') {
callback(da);
}
}
})();
使用:
如果需要同时访问多个异域文件,可以像下面zhe样写回diao函数,浏览器異步载入 iframe 的机制形成了天生的 JS 跨域异步访问。
这shi跨域请求的主页面 JS diao用:
Javascript代碼
<script language="javascript">
var _str = '', _cnt = 0;
function myfunc( id ) {
return function( data ) {
_str += id + ':' + data + '\n';
++_cnt;
if (_cnt >= 4) alert(_str);
};
}
var _links = [
{ id: 4, url: 'http://www.aaa.com/test4.html' },
{ id: 5, url: 'http://www.bbb.com/test5.html' },
{ id: 6, url: 'http://www.ccc.com/test6.html' },
{ id: 7, url: 'http://www.ddd.com/test7.html' }
];
function dosome() {
for (var _i=0; _i<_links.length; ++_i) {
wnRequest.send(_links[_i].url, myfunc(_links[_i].id));
}
// 跨域本地数据转递
wnRequest.setname('这里可能是一串加密用Demi钥哦,俺从 https 那边过来滴!', 'http://www.eee.com/test8.html');
}
</script>
<script language="javascript">
var _str = '', _cnt = 0;
function myfunc( id ) {
return function( data ) {
_str += id + ':' + data + '\n';
++_cnt;
if (_cnt >= 4) alert(_str);
};
}
var _links = [
{ id: 4, url: 'http://www.aaa.com/test4.html' },
{ id: 5, url: 'http://www.bbb.com/test5.html' },
{ id: 6, url: 'http://www.ccc.com/test6.html' },
{ id: 7, url: 'http://www.ddd.com/test7.html' }
];
function dosome() {
for (var _i=0; _i<_links.length; ++_i) {
wnRequest.send(_links[_i].url, myfunc(_links[_i].id));
}
// 跨域本地数據zhuan遞
wnRequest.setname('這里ke能是一串加密用的密钥哦,俺从 https 那边过來滴!', 'http://www.eee.com/test8.html');
}
</script>
http://www.aaa.com/test4.html 中的内容:(跨域网络數ju傳递)
Javascript代碼
<script type="text/javascript">
window.name='返hui的数據,可以是 JSON 格式';
</script>
<script type="text/javascript">
window.name='返回的數ju,可以是 JSON 格shi';
</script>
http://www.eee.com/test8.html 中的内容:(跨域本地数据转递应用。注意:這里是普通的 http xie议)
Javascript代碼
<script type="text/javascript">
if (window.name) {
alert(window.name);
// 存储或chu理 name 值
// 可存在 Cookie 中,如果bu希望 Cookie 上传泄露出去,可設置其 secure 属性
window.name = null;
}
/*
try {
top.location.hostname;
if (top.location.hostname != window.location.hostname) {
top.location.href =window.location.href;
}
} catch(e) {
top.location.href = window.location.href;
}
*/
</script>
<script type="text/javascript">
if (window.name) {
alert(window.name);
// 存储或处理 name zhi
// 可存在 Cookie 中,如果不希Wang Cookie 上传泄露出去,可设置其 secure 属性
window.name = null;
}
/*
try {
top.location.hostname;
if (top.location.hostname != window.location.hostname) {
top.location.href =window.location.href;
}
} catch(e) {
top.location.href = window.location.href;
}
*/
</script>
呵呵……是否期待下一篇文章《普通 http 网络下数ju的安全传輸》呢?
注: 附件包含本跨域实现和前幾篇关于 JS 文zi加mi算法的实xian代码。
===============================================================================
修 订:
Javascript代碼
frame.contentWindow.location = wnRequest._proxyUrl;
frame.contentWindow.location = wnRequest._proxyUrl;
如此赋值在 firefox 中会导致历史记录的产生,可用 Location.replace() 代替,如下:
Javascript代码
frame.contentWindow.location.replace(wnRequest._proxyUrl);
frame.contentWindow.location.replace(wnRequest._proxyUrl);
欢迎来到Java学xi者論坛,轉载请注明de址:http://www.javaxxz.com. |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|