疯狂的跨域技术,项目中打开新窗口的3种方式

2.使用window.open()直接打开外部窗口,在外部窗口中处理完成所有的操作后回到原来的页面,原来的页面出现一个确认是否完成操作的弹框。点击确认或者“cancel”之后接着调用其他的接口。

1,跨域的情况
如果是www.a.com/1.html链接到www.b.com/2.html,这种情况会丢失
2,利用的javascript对location的操作
比如1.html页面是通过location.href=”2.html”跳转到2.html的,在2.html的window.opener也是null,无法获取
3,利用浏览器的拖拽功能
现在的浏览器基本都是支持多tab浏览了,如果是利用拖拽链接的tab,在新tab的网页中也是无法获取window.opener

这篇文章写得很清晰,所以转过来,格式上做了下编辑。

{ let creditCarWin = null; let s = null; const stopF = () => { clearInterval(s); creditCarWin = null; s = null; callback(); }; const checkCloseWindowOrNot= () => { if (creditCarWin != null creditCarWin.closed) { stopF(); } }; const openCreditCard = () => { try { creditCarWin = openWin(url, 'CreditCard'); creditCarWin.focus(); runF(); } catch (e) { Util.NotificationUtil('error', { description: lang.openWindowError }) } }; const runF = () => { s = setInterval(checkCloseWindowOrNot, 500); }; openCreditCard();}," title="" data-original-title="复制">

但下面的情况,window.opener的值为null

另外,postMessage方式正以意想不到的速度得到各种新浏览器的支持,应予以着重考虑。

1.使用iframe(注意Iframe的高度默认150px,如果要改变iframe的高度,只能设置成具体的像素值,不能是百分比)

opener.html

 代码如下

复制代码

<html>
<body>
<form name=form1>
<input type=text name=inpu >
<input type=button  onclick="javascript:window.open('back2opener.html?toname=opener.form1.inpu');">
</form>
</body>
</html>

  JavaScript是一种在Web开发中经常使用的前端动态脚本技术。在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略)。这一策略对于JavaScript代码能够访问的页面内容做了很重要的限制,即JavaScript只能访问与包含它的文档在同一域下的内容。

detectCreditCardFilledOut: (callback, url, openWin) = { let creditCarWin = null; let s = null; const stopF = () = { clearInterval(s); creditCarWin = null; s = null; callback(); }; const checkCloseWindowOrNot= () = { if (creditCarWin != null  creditCarWin.closed) { stopF(); } }; const openCreditCard = () = { try { creditCarWin = openWin(url, 'CreditCard'); creditCarWin.focus(); runF(); } catch (e) { Util.NotificationUtil('error', { description: lang.openWindowError }) } }; const runF = () = { s = setInterval(checkCloseWindowOrNot, 500); }; openCreditCard();},

在JS中,window.opener只是对弹出窗口的母窗口的一个引用。比如:
a.html中,通过点击按钮等方式window.open出一个新的窗口b.html。那么在b.html中,就可以通过window.opener(省略写为opener)来引用a.html,包括a.html的document等对象,操作a.html的内容。
假如这个引用失败,那么将返回null。所以在调用opener的对象前,要先判断对象是否为null,否则会出现“对象为空或者不存在”的JS错误。  

  然而,当进行一些比较深入的前端编程的时候,不可避免地需要进行跨域操作,这时候“同源策略”就显得过于苛刻。本文就这个问题,概括了跨域所需要的一些技术。

时间: 2018-12-21阅读: 326标签: 窗口

例子

(一)不同子域的跨域技术。

  我们分两个问题来分别讨论:第一个问题是如何跨不同子域进行JavaScript调用;第二个问题是如何向不同子域提交Ajax请求。

先来解决第一个问题,假设example.com域下有两个不同子域:abc.example.com和def.example.com。现在假设在def.example.com下面有一个页面,里面定义了一个JavaScript函数:

function funcInDef() {
   .....
}

 

 

  我们想在abc.example.com下的某个页面里调用上面的函数。再假设我们要讨论的abc.example.com下面的这个页面是以iframe形式嵌入在def.example.com下面那个页面里的,这样我们可能试图在iframe里做如下调用:

window.top.funcInDef();

 

 

  好,我们注意到,这个调用是被前面讲到的“同源策略”所禁止的,JavaScript引擎会直接抛出一个异常。

  为了实现上述调用,我们可以通过修改两个页面的domain属性的方法做到。例如,我们可以将上面在abc.example.com和def.example.com下的两个页面的顶端都加上如下的JavaScript代码片段:

<script type="text/javascript">
    document.domain = "example.com";
</script> 

 

 

  这样,两个页面就变为同域了,前面的调用也可以正常执行了。

  这里需要注意的一点是,一个页面的document.domain属性只能设置成一个更顶级的域名(除了一级域名),但不能设置成比当前域名更深层的子域名。例如,abc.example.com的页面只能将它的domain设置成example.com,不能设置成sub.abc.example.com,当然也不能设置成一级域名com。

  上面的例子讨论的是两个页面属于iframe嵌套关系的情况,当两个页面是打开与被打开的关系时,原理也完全一样。

  下面我们来解决第二个问题:如何向不同子域提交Ajax请求。

  通常情况下,我们会用与下面类似的代码来创建一个XMLHttpRequest对象:

图片 1图片 2代码

factories = [
    function() { return new XMLHttpRequest(); },
    function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
    function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
];
function newRequest() {
    for(var i = 0; i < factories.length; i++) {
        try{
            var factory = factories[i];
            return factory();
        } catch(e) {}
    }
    return null;

  上面的代码中引用ActiveXObject,是为了兼容IE6系列浏览器。每次我们调用newRequest函数,就获得了一个刚刚创建的Ajax对象,然后用这个Ajax对象来发送HTTP请求。例如,下面的代码向abc.example.com发送了一个GET请求:

var request = newRequest();
request.open("GET", "" );
request.send(null);

 

 

  假设上面的代码包含在一个abc.example.com域名下的页面里,则这个GET请求可以正常发送成功,没有任何问题。然而,如果现在要向def.example.com发送请求,则出现跨域问题,JavaScript引擎抛出异常。

  解决的办法是,在def.example.com域下放置一个跨域文件,假设叫crossdomain.html;然后将前面的newRequest函数的定义移到这个跨域文件中;最后像之前修改document.domain值的做法一样,在crossdomain.html文件和abc.example.com域下调用Ajax的页面顶端,都加上:

<script type="text/javascript">
    document.domain = "example.com";
</script>

 

 

  为了使用跨域文件,我们在abc.example.com域下调用Ajax的页面中嵌入一个隐藏的指向跨域文件的iframe,例如:

<iframe name="xd_iframe" style="display:none" src=";

 

 

  这时abc.example.com域下的页面和跨域文件crossdomain.html都在同一个域(example.com)下,我们可以在abc.example.com域下的页面中去调用crossdomain.html中的newRequest函数:

var request = window.frames["xd_iframe"].newRequest();

 

 

  这样获得的request对象,就可以向

3.使用window.open()在当前窗口打开另一个窗口,在新开窗口中操作完成之后,关闭该窗口,在当前窗口中监听新窗口什么时候关闭,一旦检测到窗口关闭就执行回调。使用这种方式需要考虑浏览器的跨域问题,在ie上如果使用window.open()打开跨域了的窗口,window.open()是获取不到window对象的。

back2opener.html

 代码如下

复制代码

<html>
<body>
<form name=form1>
<input type=text name=inpu >

  <a class=under href=# onclick="{opener.document.form1.inpu.value+='孙超,';}">添加</a>
</form>
</body>
</html>

JS代码:

 代码如下

复制代码

window.open();

而当支付成功后,需要关闭支付平台支付成功界面,并在客户端加载客户端支付成功页面,JS代码:
window.opener.location.href=url;window.close(); 

补充一下关于window.opener与js window.parent差异

window.parent和window.opener区别来讲的,我们如果要用到iframe的值传到另一框架就要用到 :

 代码如下

复制代码

window.opener.document.getElementById(name).value = uvalue;

这种形式哦。

window.parent能获取一个框架的父窗口或父框架。顶层窗口的parent引用的是它本身。
 
可以用这一点特性来判断这个窗口是否是顶层窗口。如:

 代码如下

复制代码

function IsTopWindow( win )
{
    if( win.parent == win ) return true;
    else return false;
}

window.opener引用的是window.open打开的页面的父页面。

opener即谁打开我的,比如A页面利用window.open弹出了B页面窗口,那么A页面所在窗口就是B页面的opener,在B页面通过opener对象可以访问A页面。

parent表示父窗口,比如一个A页面利用iframe或frame调用B页面,那么A页面所在窗口就是B页面的parent。

在JS中,window.opener只是对弹出窗口的母窗口的一个引用。比如:
a.html中,通过点击按钮等方式window.open出一个新的窗口b.html。那么在b.html中,就可以通过 window.opener(省略写为opener)来引用a.html,包括a.html的document等对象,操作a.html的内容。假如这个引用失败,那么将返回null。所以在调用opener的对象前,要先判断对象是否为null,否则会出现“对象为空或者不存在”的JS错误。
 
window.opener 返回的是创建当前窗口的那个窗口的引用,比如点击了a.htm上的一个链接而打开了b.htm,然后我们打算在b.htm上输入一个值然后赋予a.htm上的一个id为“name”的textbox中,就可以写为:

 代码如下

复制代码

window.opener.document.getElementById("name").value = "输入的数据";

以前一直认为wi...

  JavaScript这个安全策略在进行多iframe或多窗口编程、以及Ajax编程时显得尤为重要。根据这个策略,在baidu.com下的页面中包含的JavaScript代码,不能访问在google.com域名下的页面内容;甚至不同的子域名之间的页面也不能通过JavaScript代码互相访问。对于Ajax的影响在于,通过XMLHttpRequest实现的Ajax请求,不能向不同的域提交请求,例如,在abc.example.com下的页面,不能向def.example.com提交Ajax请求,等等。

 

4. window.postMessage

  window.postMessage是HTML标准的下一个版本HTML5支持的一个新特性。受当前互联网技术突飞猛进的影响,浏览器跨域通信的需求越来越强烈,HTML标准终于把跨域通信考虑进去了。但目前HTML5仍然只是一个draft。

  window.postMessage是一个安全的实现直接跨域通信的方法。但是目前并不是所有浏览器都能支持,只有Firefox 3、Safari 4和IE8可以支持这个调用。

使用它向其它窗口发送消息的调用方式大概如下:

otherWindow.postMessage(message, targetOrigin);

 

 

  在接收的窗口,需要设置一个事件处理函数来接收发过来的消息:

window.addEventListener("message", receiveMessage, false);
function receiveMessage(event){ 
    if (event.origin!== "") 
        return;
}

 

 

  消息包含三个属性:data、origin(携带发送窗口所在域的真实信息)和source(代表发送窗口的handle)。

  安全性考虑:使用window.postMessage,必需要使用消息的origin和source属性来验证发送者的身份,否则会造成XSS漏洞。

  window.postMessage在功能上同iframe实现的跨域功能同样强大,并且使用简单,效率更高,但缺点是它目前在浏览器兼容方面有待提高。


 

需要对原文补充的是,在IE6,IE7下可利用IE的Opener可赋值为Object或Function的漏洞,提供postMessage方案的补充方案:

主页面:

 图片 3代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ";

<html xmlns=";
<head>
    <title>CrossDomain</title>
</head>
<body>
    <iframe src="" 
        frameborder="0" visible="false" height="0" width="0" id="ifrChild"></iframe>
    
    <script type="text/javascript">
        var child = document.getElementById("ifrChild");
        var openerObject = {
                funcInParent:function(arg){
                    alert(arg);
                    alert('executed by a function in parent page');
                }
            }
            
        if(!+'v1' && !'1'[0]){ //test browser is ie6 or ie7    
            //crack
            child.contentWindow.opener = openerObject;
        }
        else{
            //postMessage showtime
        }
        
        function onClick(){
            //debugger;
            openerObject.funcInIframe('data from parent page ');
        }
    </script>
    <input type="button" value="click me" onclick="onClick()" />
</body>
</html>

用iframe内嵌其它域下的页面:

图片 4图片 5代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ";

<html xmlns=";
<head>
               <script type="text/javascript">
                        onload = function(){
                                if(!+'v1' && !'1'[0]){ // test browser if is ie6 or ie7
                                        window.opener.funcInIframe=function(arg){
                                                alert(arg);
                                                alert('executed by a function in iframe');
                                        }
                                        window.opener.funcInParent('data from iframe')
                                }
                        }
                </script>
        </head>
        <body>
        </body>
</html>

 

 

window.opener在js中是打开新窗口,下面我来给各位同学详细介绍关于window.opener一些使用方法与总结,各位朋友可进入参考。

(二)完全不同域的跨域技术。

  如果顶级域名都不相同,例如example1.com和example2.com之间想通过JavaScript在前端通信,则所需要的技术更复杂些。

  在讲解不同域的跨域技术之前,我们首先明确一点,下面要讲的技术也同样适用于前面跨不同子域的情况,因为跨不同子域只是跨域问题的一个特例。当然,在恰当的情况下使用恰当的技术,能够保证更优的效率和更高的稳定性。

  简言之,根据不同的跨域需求,跨域技术可以归为下面几类:

1、JSONP跨域GET请求
2、通过iframe实现跨域
3、flash跨域HTTP请求
4、window.postMessage

  下面详细介绍各种技术。

以前一直认为window.opener只有在window.open方法打开下的窗口才可以访问,没想到即使是a链接打开的页面的照样可以访问。window.opener指向父窗口,也就是来源窗口。可以利用window.opener获取来源页面location.href信息等,也可以操作来源 页面的DOM,十分强大

  下面我们分两种情况讨论跨域技术:首先讨论不同子域的跨域技术,然后讨论完全不同域的跨域技术。

原贴地址:http://itgeeker.com/mathml/readpaper?pid=53

 

3. 利用flash实现跨域HTTP请求

  据称,flash在浏览器中的普及率高达90%以上。

  flash代码和JavaScript代码之间可以互相调用,并且flash的“安全沙箱”机制与JavaScript的安全机制并不尽相同,因此,我们可以利用flash来实现跨域提交HTTP请求(支持GET/POST等)。

  例如,我们用浏览器访问

  这个请求能否被成功发送,取决于在example3.com的根路径下是否放置了一个crossdomain.xml以及这个crossdomain.xml的配置如何。flash的“安全沙箱”会保证:仅当example3.com服务器在根路径下确实放置了crossdomain.xml文件并且在这个文件中配置了允许接受来自example2.com的flash的请求时,这个请求才能真正成功。下面是一个crossdomain.xml文件内容的例子:

<?xml version="1.0"?>
<cross-domain-policy>
    <allow-access-from domain="example2.com" />
</cross-domain-policy>

 

 

2. 通过iframe实现跨域。

  iframe跨域的方式,功能强于JSONP,它不仅能用来跨域完成HTTP请求,还能在前端跨域实现JavaScript调用。因此,完全不同域的跨域问题,通常采用iframe的方式来解决。

  与JSONP技术通过创建<script>节点向不同的域提交GET请求的工作方式类似,我们也可以通过在

  为了解决这个问题,我们需要在example1.com下放置一个跨域文件,比如路径是

  当

  第一个选择是,它可以在iframe中做一个302跳转,跳转到跨域文件

  另一个选择是,它可以在返回的页面中再嵌入一个iframe,指向跨域文件,同时也是将返回结果经过URL编码之后作为参数缀在跨域文件URL后面。

  在跨域文件中,包含一段JavaScript代码,这段代码完成的功能,是从URL中提取结果参数,经过一定处理后调用原来的

  根据前面的叙述,有了跨域文件之后,我们就可以实现通过iframe方式在不同域之间进行JavaScript调用。这个调用过程可以完全跟HTTP请求无关,例如有些站点可以支持动态地调整在页面中嵌入的第三方iframe的高度,这其实是通过在第三方iframe里面检测自己页面的高度变化,然后通过跨域方式的函数调用将这个变化告知父窗口来完成的。

  既然利用iframe可以实现跨域JavaScript调用,那么跨域提交POST请求等其它类型的HTTP请求就不是难事。例如我们可以跨域调用目标域的JavaScript代码在目标域下提交Ajax请求(GET/POST/etc.),然后将返回的结果再跨域传原来的域。

  使用iframe跨域,优点是功能强大,支持各种浏览器,几乎可以完成任何跨域想做的事情;缺点是实现复杂,要处理很多浏览器兼容问题,并且传输的数据不宜过大,过大了可能会超过浏览器对URL长度的限制,要考虑对数据进行分段传输等。

1. JSONP。

  利用在页面中创建<script>节点的方法向不同域提交HTTP请求的方法称为JSONP,这项技术可以解决跨域提交Ajax请求的问题。JSONP的工作原理如下所述:

  假设在

图片 6图片 7代码

var eleScript= document.createElement("script");
eleScript.type = "text/javascript";
eleScript.src = "";
document.getElementsByTagName("HEAD")[0].appendChild(eleScript);

 

 

  当GET请求从

  JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。

  JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

本文由澳门威斯尼人平台登录发布于Web前端,转载请注明出处:疯狂的跨域技术,项目中打开新窗口的3种方式

相关阅读