什么是跨域
<P> JAVASCRIPT出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入IFRAME或是AJAX应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:</P>
<P> 首先什么是跨域,简单地理解就是因为JAVASCRIPT同源策略的限制,A.COM 域名下的JS无法操作B.COM或是C.A.COM域名下的对象。更详细的说明可以看下表:<IMG STYLE="DISPLAY: BLOCK; MARGIN-LEFT: AUTO; MARGIN-RIGHT: AUTO" ALT="" SRC="HTTP://PIC001.CNBLOGS.COM/IMAGES/2011/145819/2011022222433934.JPG"></P>
<DL>
<DT> 特别注意两点:</DT>
<DD>第一,如果是协议和端口造成的跨域问题前台是无能为力的,</DD>
<DD>第二:在跨域问题上,域仅仅是通过URL的首部来识别而不会去尝试判断相同的IP地址对应着两个域或两个域是否在同一个IP上。<BR>URL的首部指WINDOW.LOCATION.PROTOCOL +WINDOW.LOCATION.HOST,也可以理解为DOMAINS, PROTOCOLS AND PORTS MUST MATCH。</DD></DL>
<P> 接下来简单地总结一下在前台一般处理跨域的办法,后台PROXY这种方案牵涉到后台配置,这里就不阐述了,有兴趣的可以看看YAHOO的这篇文章:《<A HREF="HTTP://DEVELOPER.YAHOO.COM/JAVASCRIPT/HOWTO-PROXY.HTML" TARGET=_BLANK>JAVASCRIPT: USE A WEB PROXY FOR CROSS-DOMAIN XMLHTTPREQUEST CALLS</A>》</P>
<H3> 1、DOCUMENT.DOMAIN+IFRAME的设置</H3>
<P><SPAN CLASS=HIGHLIGHT> 对于主域相同而子域不同的例子,可以通过设置DOCUMENT.DOMAIN的办法来解决</SPAN>。具体的做法是可以在HTTP://WWW.A.COM/A.HTML和HTTP://SCRIPT.A.COM/B.HTML两个文件中分别加上DOCUMENT.DOMAIN = A.COM;然后通过A.HTML文件中创建一个IFRAME,去控制IFRAME的CONTENTDOCUMENT,这样两个JS文件之间就可以交互了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把SCRIPT.A.COM的DOMIAN设为ALIBABA.COM那显然是会报错地!代码如下:</P>
<P> WWW.A.COM上的A.HTML </P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #000000">DOCUMENT.DOMAIN </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">A.COM</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR></SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> IFR </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> DOCUMENT.CREATEELEMENT(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">IFRAME</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">);<BR>IFR.SRC </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">HTTP://SCRIPT.A.COM/B.HTML</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR>IFR.STYLE.DISPLAY </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">NONE</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR>DOCUMENT.BODY.APPENDCHILD(IFR);<BR>IFR.ONLOAD </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000">(){<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> DOC </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> IFR.CONTENTDOCUMENT </SPAN><SPAN STYLE="COLOR: #000000">||</SPAN><SPAN STYLE="COLOR: #000000"> IFR.CONTENTWINDOW.DOCUMENT;<BR> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 在这里操纵B.HTML</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> ALERT(DOC.GETELEMENTSBYTAGNAME(</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">H1</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">)[</SPAN><SPAN STYLE="COLOR: #000000">0</SPAN><SPAN STYLE="COLOR: #000000">].CHILDNODES[</SPAN><SPAN STYLE="COLOR: #000000">0</SPAN><SPAN STYLE="COLOR: #000000">].NODEVALUE);<BR>};<BR><BR>SCRIPT.A.COM上的B.HTML<BR><BR>DOCUMENT.DOMAIN </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">A.COM</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;</SPAN></DIV></PRE></DIV>
<P> 这种方式适用于{WWW.KUQIN.COM, KUQIN.COM, SCRIPT.KUQIN.COM, CSS.KUQIN.COM}中的任何页面相互通信。</P>
<P> 备注:某一页面的DOMAIN默认等于WINDOW.LOCATION.HOSTNAME。主域名是不带WWW的域名,例如A.COM,主域名前面带前缀的通常都为二级域名或多级域名,例如WWW.A.COM其实是二级域名。 DOMAIN只能设置为主域名,不可以在B.A.COM中将DOMAIN设置为C.A.COM。</P>
<DL>
<DT> 问题:</DT>
<DD>1、安全性,当一个站点(B.A.COM)被攻击后,另一个站点(C.A.COM)会引起安全漏洞。</DD>
<DD>2、如果一个页面中引入多个IFRAME,要想能够操作所有IFRAME,必须都得设置相同DOMAIN。</DD></DL>
<H3> 2、动态创建SCRIPT</H3>
<P><SPAN CLASS=HIGHLIGHT> 虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的FUNCTION(包括操作COOKIE、DOM等等)</SPAN>。根据这一点,可以方便地通过创建SCRIPT节点的方法来实现完全跨域的通信。具体的做法可以参考YUI的<A HREF="HTTP://DEVELOPER.YAHOO.COM/YUI/GET/" TARGET=_BLANK>GET UTILITY</A></P>
<P> 这里判断SCRIPT节点加载完毕还是蛮有意思的:IE只能通过SCRIPT的READYSTATECHANGE属性,其它浏览器是SCRIPT的LOAD事件。以下是部分判断SCRIPT加载完毕的方法。</P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #000000">JS.ONLOAD </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> JS.ONREADYSTATECHANGE </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000">() {<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">IF</SPAN><SPAN STYLE="COLOR: #000000"> (</SPAN><SPAN STYLE="COLOR: #000000">!</SPAN><SPAN STYLE="COLOR: #0000FF">THIS</SPAN><SPAN STYLE="COLOR: #000000">.READYSTATE </SPAN><SPAN STYLE="COLOR: #000000">||</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">THIS</SPAN><SPAN STYLE="COLOR: #000000">.READYSTATE </SPAN><SPAN STYLE="COLOR: #000000">===</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">LOADED</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">||</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">THIS</SPAN><SPAN STYLE="COLOR: #000000">.READYSTATE </SPAN><SPAN STYLE="COLOR: #000000">===</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">COMPLETE</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">) {<BR> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> CALLBACK在此处执行</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> JS.ONLOAD </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> JS.ONREADYSTATECHANGE </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">NULL</SPAN><SPAN STYLE="COLOR: #000000">;<BR> }<BR>};</SPAN></DIV></PRE></DIV>
<H3> 3、利用IFRAME和LOCATION.HASH</H3>
<P> 这个办法比较绕,但是可以解决完全跨域情况下的脚步置换问题。原理是利用LOCATION.HASH来进行传值。在URL: HTTP://A.COM#HELLOWORD中的#HELLOWORLD就是LOCATION.HASH,改变HASH并不会导致页面刷新,所以可以利用HASH值来进行数据传递,当然数据容量是有限的。假设域名A.COM下的文件CS1.HTML要和CNBLOGS.COM域名下的CS2.HTML传递信息,CS1.HTML首先创建自动创建一个隐藏的IFRAME,IFRAME的SRC指向CNBLOGS.COM域名下的CS2.HTML页面,这时的HASH值可以做参数传递用。</P>
<P> CS2.HTML响应请求后再将通过修改CS1.HTML的HASH值来传递数据(<SPAN CLASS=GRAY>由于两个页面不在同一个域下IE、CHROME不允许修改PARENT.LOCATION.HASH的值,所以要借助于A.COM域名下的一个代理IFRAME;FIREFOX可以修改</SPAN>)。同时在CS1.HTML上加一个定时器,隔一段时间来判断LOCATION.HASH的值有没有变化,一点有变化则获取获取HASH值。代码如下:</P>
<P> 先是A.COM下的文件CS1.HTML文件: </P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000"> STARTREQUEST(){<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> IFR </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> DOCUMENT.CREATEELEMENT(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">IFRAME</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">);<BR> IFR.STYLE.DISPLAY </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">NONE</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR> IFR.SRC </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">HTTP://WWW.CNBLOGS.COM/LAB/CSCRIPT/CS2.HTML#PARAMDO</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR> DOCUMENT.BODY.APPENDCHILD(IFR);<BR>}<BR><BR></SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000"> CHECKHASH() {<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">TRY</SPAN><SPAN STYLE="COLOR: #000000"> {<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> DATA </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> LOCATION.HASH </SPAN><SPAN STYLE="COLOR: #000000">?</SPAN><SPAN STYLE="COLOR: #000000"> LOCATION.HASH.SUBSTRING(</SPAN><SPAN STYLE="COLOR: #000000">1</SPAN><SPAN STYLE="COLOR: #000000">) : </SPAN><SPAN STYLE="COLOR: #000000">''</SPAN><SPAN STYLE="COLOR: #000000">;<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">IF</SPAN><SPAN STYLE="COLOR: #000000"> (CONSOLE.LOG) {<BR> CONSOLE.LOG(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">NOW THE DATA IS </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">+</SPAN><SPAN STYLE="COLOR: #000000">DATA);<BR> }<BR> } </SPAN><SPAN STYLE="COLOR: #0000FF">CATCH</SPAN><SPAN STYLE="COLOR: #000000">(E) {};<BR>}<BR>SETINTERVAL(CHECKHASH, </SPAN><SPAN STYLE="COLOR: #000000">2000</SPAN><SPAN STYLE="COLOR: #000000">);<BR><BR>CNBLOGS.COM域名下的CS2.HTML:<BR><BR></SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000">模拟一个简单的参数处理操作</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #0000FF">SWITCH</SPAN><SPAN STYLE="COLOR: #000000">(LOCATION.HASH){<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">CASE</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">#PARAMDO</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">:<BR> CALLBACK();<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">BREAK</SPAN><SPAN STYLE="COLOR: #000000">;<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">CASE</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">#PARAMSET</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">:<BR> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000">DO SOMETHING……</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">BREAK</SPAN><SPAN STYLE="COLOR: #000000">;<BR>}<BR><BR></SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000"> CALLBACK(){<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">TRY</SPAN><SPAN STYLE="COLOR: #000000"> {<BR> PARENT.LOCATION.HASH </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">SOMEDATA</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR> } </SPAN><SPAN STYLE="COLOR: #0000FF">CATCH</SPAN><SPAN STYLE="COLOR: #000000"> (E) {<BR> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> IE、CHROME的安全机制无法修改PARENT.LOCATION.HASH,</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 所以要利用一个中间的CNBLOGS域下的代理IFRAME</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> IFRPROXY </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> DOCUMENT.CREATEELEMENT(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">IFRAME</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">);<BR> IFRPROXY.STYLE.DISPLAY </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">NONE</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR> IFRPROXY.SRC </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">HTTP://A.COM/TEST/CSCRIPT/CS3.HTML#SOMEDATA</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">; </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 注意该文件在"A.COM"域下</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> DOCUMENT.BODY.APPENDCHILD(IFRPROXY);<BR> }<BR>}</SPAN></DIV></PRE></DIV>
<P> A.COM下的域名CS3.HTML</P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000">因为PARENT.PARENT和自身属于同一个域,所以可以改变其LOCATION.HASH的值</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000">PARENT.PARENT.LOCATION.HASH </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> SELF.LOCATION.HASH.SUBSTRING(</SPAN><SPAN STYLE="COLOR: #000000">1</SPAN><SPAN STYLE="COLOR: #000000">);</SPAN></DIV></PRE></DIV>
<P> 当然这样做也存在很多缺点,诸如数据直接暴露在了URL中,数据容量和类型都有限等……</P>
<H3> 4、WINDOW.NAME实现的跨域数据传输</H3>
<P> 文章较长列在此处不便于阅读,详细请看&NBSP;<A HREF="HTTP://WWW.CNBLOGS.COM/RAINMAN/ARCHIVE/2011/02/21/1960044.HTML" TARGET=_BLANK>WINDOW.NAME实现的跨域数据传输</A>。</P>
<H3> 5、使用HTML5 POSTMESSAGE</H3>
<P> HTML5中最酷的新功能之一就是 跨文档消息传输CROSS DOCUMENT MESSAGING。下一代浏览器都将支持这个功能:CHROME 2.0+、INTERNET EXPLORER 8.0+, FIREFOX 3.0+, OPERA 9.6+, 和 SAFARI 4.0+ 。 FACEBOOK已经使用了这个功能,用POSTMESSAGE支持基于WEB的实时消息传递。 </P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #000000">OTHERWINDOW.POSTMESSAGE(MESSAGE, TARGETORIGIN);</SPAN></DIV></PRE></DIV>
<DL>
<DD><SPAN CLASS=GREEN>OTHERWINDOW: </SPAN>对接收信息页面的WINDOW的引用。可以是页面中IFRAME的CONTENTWINDOW属性;WINDOW.OPEN的返回值;通过NAME或下标从WINDOW.FRAMES取到的值。<BR><SPAN CLASS=GREEN>MESSAGE: </SPAN>所要发送的数据,STRING类型。<BR><SPAN CLASS=GREEN>TARGETORIGIN: </SPAN>用于限制OTHERWINDOW,*表示不作限制</DD></DL>
<P> A.COM/INDEX.HTML中的代码:</P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #000000">&NBSP;</SPAN><SPAN STYLE="COLOR: #000000">IFRAME ID</SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">IFR</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000"> SRC</SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">B.COM/INDEX.HTML</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">&NBSP;</SPAN><SPAN STYLE="COLOR: #000000">/</SPAN><SPAN STYLE="COLOR: #000000">IFRAME</SPAN><SPAN STYLE="COLOR: #000000"><BR></SPAN><SPAN STYLE="COLOR: #000000">&NBSP;</SPAN><SPAN STYLE="COLOR: #000000">SCRIPT TYPE</SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">TEXT/JAVASCRIPT</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000"><BR>WINDOW.ONLOAD </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000">() {<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> IFR </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> DOCUMENT.GETELEMENTBYID(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">IFR</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">);<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> TARGETORIGIN </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">HTTP://B.COM</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">; </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 若写成'HTTP://B.COM/C/PROXY.HTML'效果一样</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 若写成'HTTP://C.COM'就不会执行POSTMESSAGE了</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> IFR.CONTENTWINDOW.POSTMESSAGE(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">I WAS THERE!</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">, TARGETORIGIN);<BR>};<BR></SPAN><SPAN STYLE="COLOR: #000000">/</SPAN><SPAN STYLE="COLOR: #000000">SCRIPT</SPAN></DIV></PRE></DIV>
<P> B.COM/INDEX.HTML中的代码:</P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #000000">SCRIPT TYPE</SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">TEXT/JAVASCRIPT</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000"><BR> WINDOW.ADDEVENTLISTENER(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">MESSAGE</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">, </SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000">(EVENT){<BR> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 通过ORIGIN属性判断消息来源地址</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">IF</SPAN><SPAN STYLE="COLOR: #000000"> (EVENT.ORIGIN </SPAN><SPAN STYLE="COLOR: #000000">==</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">HTTP://A.COM</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">) {<BR> ALERT(EVENT.DATA); </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 弹出"I WAS THERE!"</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> ALERT(EVENT.SOURCE); </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 对A.COM、INDEX.HTML中WINDOW对象的引用</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 但由于同源策略,这里EVENT.SOURCE不可以访问WINDOW对象</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> }<BR> }, </SPAN><SPAN STYLE="COLOR: #0000FF">FALSE</SPAN><SPAN STYLE="COLOR: #000000">);<BR></SPAN><SPAN STYLE="COLOR: #000000">/</SPAN><SPAN STYLE="COLOR: #000000">SCRIPT</SPAN></DIV></PRE></DIV>
<H3> 6、利用FLASH</H3>
<P> 这是从YUI3的IO组件中看到的办法,具体可见<A HREF="HTTP://DEVELOPER.YAHOO.COM/YUI/3/IO/" TARGET=_BLANK>HTTP://DEVELOPER.YAHOO.COM/YUI/3/IO/</A>。<BR> 可以看在ADOBE DEVELOPER CONNECTION看到更多的跨域代理文件规范:<A HREF="HTTP://WWW.ADOBE.COM/DEVNET/ARTICLES/CROSSDOMAIN_POLICY_FILE_SPEC.HTML" TARGET=_BLANK>ROSS-DOMAIN POLICY FILE SPECIFICATIONS</A>、<A HREF="HTTP://WWW.ADOBE.COM/DEVNET/ARTICLES/CROSSDOMAIN_POLICY_FILE_SPEC.HTML" TARGET=_BLANK>HTTP HEADERS BLACKLIST</A>。</P>
<P> JAVASCRIPT出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入IFRAME或是AJAX应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:</P>
<P> 首先什么是跨域,简单地理解就是因为JAVASCRIPT同源策略的限制,A.COM 域名下的JS无法操作B.COM或是C.A.COM域名下的对象。更详细的说明可以看下表:<IMG STYLE="DISPLAY: BLOCK; MARGIN-LEFT: AUTO; MARGIN-RIGHT: AUTO" ALT="" SRC="HTTP://PIC001.CNBLOGS.COM/IMAGES/2011/145819/2011022222433934.JPG"></P>
<DL>
<DT> 特别注意两点:</DT>
<DD>第一,如果是协议和端口造成的跨域问题前台是无能为力的,</DD>
<DD>第二:在跨域问题上,域仅仅是通过URL的首部来识别而不会去尝试判断相同的IP地址对应着两个域或两个域是否在同一个IP上。<BR>URL的首部指WINDOW.LOCATION.PROTOCOL +WINDOW.LOCATION.HOST,也可以理解为DOMAINS, PROTOCOLS AND PORTS MUST MATCH。</DD></DL>
<P> 接下来简单地总结一下在前台一般处理跨域的办法,后台PROXY这种方案牵涉到后台配置,这里就不阐述了,有兴趣的可以看看YAHOO的这篇文章:《<A HREF="HTTP://DEVELOPER.YAHOO.COM/JAVASCRIPT/HOWTO-PROXY.HTML" TARGET=_BLANK>JAVASCRIPT: USE A WEB PROXY FOR CROSS-DOMAIN XMLHTTPREQUEST CALLS</A>》</P>
<H3> 1、DOCUMENT.DOMAIN+IFRAME的设置</H3>
<P><SPAN CLASS=HIGHLIGHT> 对于主域相同而子域不同的例子,可以通过设置DOCUMENT.DOMAIN的办法来解决</SPAN>。具体的做法是可以在HTTP://WWW.A.COM/A.HTML和HTTP://SCRIPT.A.COM/B.HTML两个文件中分别加上DOCUMENT.DOMAIN = A.COM;然后通过A.HTML文件中创建一个IFRAME,去控制IFRAME的CONTENTDOCUMENT,这样两个JS文件之间就可以交互了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把SCRIPT.A.COM的DOMIAN设为ALIBABA.COM那显然是会报错地!代码如下:</P>
<P> WWW.A.COM上的A.HTML </P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #000000">DOCUMENT.DOMAIN </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">A.COM</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR></SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> IFR </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> DOCUMENT.CREATEELEMENT(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">IFRAME</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">);<BR>IFR.SRC </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">HTTP://SCRIPT.A.COM/B.HTML</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR>IFR.STYLE.DISPLAY </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">NONE</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR>DOCUMENT.BODY.APPENDCHILD(IFR);<BR>IFR.ONLOAD </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000">(){<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> DOC </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> IFR.CONTENTDOCUMENT </SPAN><SPAN STYLE="COLOR: #000000">||</SPAN><SPAN STYLE="COLOR: #000000"> IFR.CONTENTWINDOW.DOCUMENT;<BR> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 在这里操纵B.HTML</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> ALERT(DOC.GETELEMENTSBYTAGNAME(</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">H1</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">)[</SPAN><SPAN STYLE="COLOR: #000000">0</SPAN><SPAN STYLE="COLOR: #000000">].CHILDNODES[</SPAN><SPAN STYLE="COLOR: #000000">0</SPAN><SPAN STYLE="COLOR: #000000">].NODEVALUE);<BR>};<BR><BR>SCRIPT.A.COM上的B.HTML<BR><BR>DOCUMENT.DOMAIN </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">A.COM</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;</SPAN></DIV></PRE></DIV>
<P> 这种方式适用于{WWW.KUQIN.COM, KUQIN.COM, SCRIPT.KUQIN.COM, CSS.KUQIN.COM}中的任何页面相互通信。</P>
<P> 备注:某一页面的DOMAIN默认等于WINDOW.LOCATION.HOSTNAME。主域名是不带WWW的域名,例如A.COM,主域名前面带前缀的通常都为二级域名或多级域名,例如WWW.A.COM其实是二级域名。 DOMAIN只能设置为主域名,不可以在B.A.COM中将DOMAIN设置为C.A.COM。</P>
<DL>
<DT> 问题:</DT>
<DD>1、安全性,当一个站点(B.A.COM)被攻击后,另一个站点(C.A.COM)会引起安全漏洞。</DD>
<DD>2、如果一个页面中引入多个IFRAME,要想能够操作所有IFRAME,必须都得设置相同DOMAIN。</DD></DL>
<H3> 2、动态创建SCRIPT</H3>
<P><SPAN CLASS=HIGHLIGHT> 虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的FUNCTION(包括操作COOKIE、DOM等等)</SPAN>。根据这一点,可以方便地通过创建SCRIPT节点的方法来实现完全跨域的通信。具体的做法可以参考YUI的<A HREF="HTTP://DEVELOPER.YAHOO.COM/YUI/GET/" TARGET=_BLANK>GET UTILITY</A></P>
<P> 这里判断SCRIPT节点加载完毕还是蛮有意思的:IE只能通过SCRIPT的READYSTATECHANGE属性,其它浏览器是SCRIPT的LOAD事件。以下是部分判断SCRIPT加载完毕的方法。</P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #000000">JS.ONLOAD </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> JS.ONREADYSTATECHANGE </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000">() {<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">IF</SPAN><SPAN STYLE="COLOR: #000000"> (</SPAN><SPAN STYLE="COLOR: #000000">!</SPAN><SPAN STYLE="COLOR: #0000FF">THIS</SPAN><SPAN STYLE="COLOR: #000000">.READYSTATE </SPAN><SPAN STYLE="COLOR: #000000">||</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">THIS</SPAN><SPAN STYLE="COLOR: #000000">.READYSTATE </SPAN><SPAN STYLE="COLOR: #000000">===</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">LOADED</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">||</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">THIS</SPAN><SPAN STYLE="COLOR: #000000">.READYSTATE </SPAN><SPAN STYLE="COLOR: #000000">===</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">COMPLETE</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">) {<BR> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> CALLBACK在此处执行</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> JS.ONLOAD </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> JS.ONREADYSTATECHANGE </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">NULL</SPAN><SPAN STYLE="COLOR: #000000">;<BR> }<BR>};</SPAN></DIV></PRE></DIV>
<H3> 3、利用IFRAME和LOCATION.HASH</H3>
<P> 这个办法比较绕,但是可以解决完全跨域情况下的脚步置换问题。原理是利用LOCATION.HASH来进行传值。在URL: HTTP://A.COM#HELLOWORD中的#HELLOWORLD就是LOCATION.HASH,改变HASH并不会导致页面刷新,所以可以利用HASH值来进行数据传递,当然数据容量是有限的。假设域名A.COM下的文件CS1.HTML要和CNBLOGS.COM域名下的CS2.HTML传递信息,CS1.HTML首先创建自动创建一个隐藏的IFRAME,IFRAME的SRC指向CNBLOGS.COM域名下的CS2.HTML页面,这时的HASH值可以做参数传递用。</P>
<P> CS2.HTML响应请求后再将通过修改CS1.HTML的HASH值来传递数据(<SPAN CLASS=GRAY>由于两个页面不在同一个域下IE、CHROME不允许修改PARENT.LOCATION.HASH的值,所以要借助于A.COM域名下的一个代理IFRAME;FIREFOX可以修改</SPAN>)。同时在CS1.HTML上加一个定时器,隔一段时间来判断LOCATION.HASH的值有没有变化,一点有变化则获取获取HASH值。代码如下:</P>
<P> 先是A.COM下的文件CS1.HTML文件: </P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000"> STARTREQUEST(){<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> IFR </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> DOCUMENT.CREATEELEMENT(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">IFRAME</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">);<BR> IFR.STYLE.DISPLAY </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">NONE</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR> IFR.SRC </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">HTTP://WWW.CNBLOGS.COM/LAB/CSCRIPT/CS2.HTML#PARAMDO</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR> DOCUMENT.BODY.APPENDCHILD(IFR);<BR>}<BR><BR></SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000"> CHECKHASH() {<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">TRY</SPAN><SPAN STYLE="COLOR: #000000"> {<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> DATA </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> LOCATION.HASH </SPAN><SPAN STYLE="COLOR: #000000">?</SPAN><SPAN STYLE="COLOR: #000000"> LOCATION.HASH.SUBSTRING(</SPAN><SPAN STYLE="COLOR: #000000">1</SPAN><SPAN STYLE="COLOR: #000000">) : </SPAN><SPAN STYLE="COLOR: #000000">''</SPAN><SPAN STYLE="COLOR: #000000">;<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">IF</SPAN><SPAN STYLE="COLOR: #000000"> (CONSOLE.LOG) {<BR> CONSOLE.LOG(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">NOW THE DATA IS </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">+</SPAN><SPAN STYLE="COLOR: #000000">DATA);<BR> }<BR> } </SPAN><SPAN STYLE="COLOR: #0000FF">CATCH</SPAN><SPAN STYLE="COLOR: #000000">(E) {};<BR>}<BR>SETINTERVAL(CHECKHASH, </SPAN><SPAN STYLE="COLOR: #000000">2000</SPAN><SPAN STYLE="COLOR: #000000">);<BR><BR>CNBLOGS.COM域名下的CS2.HTML:<BR><BR></SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000">模拟一个简单的参数处理操作</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #0000FF">SWITCH</SPAN><SPAN STYLE="COLOR: #000000">(LOCATION.HASH){<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">CASE</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">#PARAMDO</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">:<BR> CALLBACK();<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">BREAK</SPAN><SPAN STYLE="COLOR: #000000">;<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">CASE</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">#PARAMSET</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">:<BR> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000">DO SOMETHING……</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">BREAK</SPAN><SPAN STYLE="COLOR: #000000">;<BR>}<BR><BR></SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000"> CALLBACK(){<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">TRY</SPAN><SPAN STYLE="COLOR: #000000"> {<BR> PARENT.LOCATION.HASH </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">SOMEDATA</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR> } </SPAN><SPAN STYLE="COLOR: #0000FF">CATCH</SPAN><SPAN STYLE="COLOR: #000000"> (E) {<BR> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> IE、CHROME的安全机制无法修改PARENT.LOCATION.HASH,</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 所以要利用一个中间的CNBLOGS域下的代理IFRAME</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> IFRPROXY </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> DOCUMENT.CREATEELEMENT(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">IFRAME</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">);<BR> IFRPROXY.STYLE.DISPLAY </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">NONE</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">;<BR> IFRPROXY.SRC </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">HTTP://A.COM/TEST/CSCRIPT/CS3.HTML#SOMEDATA</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">; </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 注意该文件在"A.COM"域下</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> DOCUMENT.BODY.APPENDCHILD(IFRPROXY);<BR> }<BR>}</SPAN></DIV></PRE></DIV>
<P> A.COM下的域名CS3.HTML</P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000">因为PARENT.PARENT和自身属于同一个域,所以可以改变其LOCATION.HASH的值</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000">PARENT.PARENT.LOCATION.HASH </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> SELF.LOCATION.HASH.SUBSTRING(</SPAN><SPAN STYLE="COLOR: #000000">1</SPAN><SPAN STYLE="COLOR: #000000">);</SPAN></DIV></PRE></DIV>
<P> 当然这样做也存在很多缺点,诸如数据直接暴露在了URL中,数据容量和类型都有限等……</P>
<H3> 4、WINDOW.NAME实现的跨域数据传输</H3>
<P> 文章较长列在此处不便于阅读,详细请看&NBSP;<A HREF="HTTP://WWW.CNBLOGS.COM/RAINMAN/ARCHIVE/2011/02/21/1960044.HTML" TARGET=_BLANK>WINDOW.NAME实现的跨域数据传输</A>。</P>
<H3> 5、使用HTML5 POSTMESSAGE</H3>
<P> HTML5中最酷的新功能之一就是 跨文档消息传输CROSS DOCUMENT MESSAGING。下一代浏览器都将支持这个功能:CHROME 2.0+、INTERNET EXPLORER 8.0+, FIREFOX 3.0+, OPERA 9.6+, 和 SAFARI 4.0+ 。 FACEBOOK已经使用了这个功能,用POSTMESSAGE支持基于WEB的实时消息传递。 </P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #000000">OTHERWINDOW.POSTMESSAGE(MESSAGE, TARGETORIGIN);</SPAN></DIV></PRE></DIV>
<DL>
<DD><SPAN CLASS=GREEN>OTHERWINDOW: </SPAN>对接收信息页面的WINDOW的引用。可以是页面中IFRAME的CONTENTWINDOW属性;WINDOW.OPEN的返回值;通过NAME或下标从WINDOW.FRAMES取到的值。<BR><SPAN CLASS=GREEN>MESSAGE: </SPAN>所要发送的数据,STRING类型。<BR><SPAN CLASS=GREEN>TARGETORIGIN: </SPAN>用于限制OTHERWINDOW,*表示不作限制</DD></DL>
<P> A.COM/INDEX.HTML中的代码:</P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #000000">&NBSP;</SPAN><SPAN STYLE="COLOR: #000000">IFRAME ID</SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">IFR</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000"> SRC</SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">B.COM/INDEX.HTML</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">&NBSP;</SPAN><SPAN STYLE="COLOR: #000000">/</SPAN><SPAN STYLE="COLOR: #000000">IFRAME</SPAN><SPAN STYLE="COLOR: #000000"><BR></SPAN><SPAN STYLE="COLOR: #000000">&NBSP;</SPAN><SPAN STYLE="COLOR: #000000">SCRIPT TYPE</SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">TEXT/JAVASCRIPT</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000"><BR>WINDOW.ONLOAD </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000">() {<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> IFR </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> DOCUMENT.GETELEMENTBYID(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">IFR</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">);<BR> </SPAN><SPAN STYLE="COLOR: #0000FF">VAR</SPAN><SPAN STYLE="COLOR: #000000"> TARGETORIGIN </SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">HTTP://B.COM</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">; </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 若写成'HTTP://B.COM/C/PROXY.HTML'效果一样</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 若写成'HTTP://C.COM'就不会执行POSTMESSAGE了</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> IFR.CONTENTWINDOW.POSTMESSAGE(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">I WAS THERE!</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">, TARGETORIGIN);<BR>};<BR></SPAN><SPAN STYLE="COLOR: #000000">/</SPAN><SPAN STYLE="COLOR: #000000">SCRIPT</SPAN></DIV></PRE></DIV>
<P> B.COM/INDEX.HTML中的代码:</P>
<DIV CLASS=CNBLOGS_CODE><PRE><DIV><!--<BR /><BR />CODE HIGHLIGHTING PRODUCED BY ACTIPRO CODEHIGHLIGHTER (FREEWARE)<BR />HTTP://WWW.CODEHIGHLIGHTER.COM/<BR /><BR />--><SPAN STYLE="COLOR: #000000">SCRIPT TYPE</SPAN><SPAN STYLE="COLOR: #000000">=</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000">TEXT/JAVASCRIPT</SPAN><SPAN STYLE="COLOR: #000000">"</SPAN><SPAN STYLE="COLOR: #000000"><BR> WINDOW.ADDEVENTLISTENER(</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">MESSAGE</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">, </SPAN><SPAN STYLE="COLOR: #0000FF">FUNCTION</SPAN><SPAN STYLE="COLOR: #000000">(EVENT){<BR> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 通过ORIGIN属性判断消息来源地址</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #0000FF">IF</SPAN><SPAN STYLE="COLOR: #000000"> (EVENT.ORIGIN </SPAN><SPAN STYLE="COLOR: #000000">==</SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">HTTP://A.COM</SPAN><SPAN STYLE="COLOR: #000000">'</SPAN><SPAN STYLE="COLOR: #000000">) {<BR> ALERT(EVENT.DATA); </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 弹出"I WAS THERE!"</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> ALERT(EVENT.SOURCE); </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 对A.COM、INDEX.HTML中WINDOW对象的引用</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> </SPAN><SPAN STYLE="COLOR: #008000">//</SPAN><SPAN STYLE="COLOR: #008000"> 但由于同源策略,这里EVENT.SOURCE不可以访问WINDOW对象</SPAN><SPAN STYLE="COLOR: #008000"><BR></SPAN><SPAN STYLE="COLOR: #000000"> }<BR> }, </SPAN><SPAN STYLE="COLOR: #0000FF">FALSE</SPAN><SPAN STYLE="COLOR: #000000">);<BR></SPAN><SPAN STYLE="COLOR: #000000">/</SPAN><SPAN STYLE="COLOR: #000000">SCRIPT</SPAN></DIV></PRE></DIV>
<H3> 6、利用FLASH</H3>
<P> 这是从YUI3的IO组件中看到的办法,具体可见<A HREF="HTTP://DEVELOPER.YAHOO.COM/YUI/3/IO/" TARGET=_BLANK>HTTP://DEVELOPER.YAHOO.COM/YUI/3/IO/</A>。<BR> 可以看在ADOBE DEVELOPER CONNECTION看到更多的跨域代理文件规范:<A HREF="HTTP://WWW.ADOBE.COM/DEVNET/ARTICLES/CROSSDOMAIN_POLICY_FILE_SPEC.HTML" TARGET=_BLANK>ROSS-DOMAIN POLICY FILE SPECIFICATIONS</A>、<A HREF="HTTP://WWW.ADOBE.COM/DEVNET/ARTICLES/CROSSDOMAIN_POLICY_FILE_SPEC.HTML" TARGET=_BLANK>HTTP HEADERS BLACKLIST</A>。</P>