我正在开发纯粹使用JavaScript的OAuth身份验证流程,我想在弹出窗口中向用户显示“授予访问权限”窗口,但它会被阻止。
如何阻止window.open
或window.showModalDialog
创建的弹出窗口被不同浏览器的弹出窗口阻止程序阻止?
答案 0 :(得分:259)
一般规则是,如果从直接用户操作未调用的javascript调用window.open
或类似内容,弹出窗口拦截器将会参与。也就是说,您可以调用window.open
以响应按钮单击而不会被弹出窗口阻止程序命中,但如果您在计时器事件中放入相同的代码,它将被阻止。呼叫链的深度也是一个因素 - 一些较旧的浏览器只查看直接呼叫者,较新的浏览器可以稍微回溯一下,看看呼叫者的呼叫者是否是鼠标点击等。尽可能保持浅,以避免弹出窗口阻止程序。
答案 1 :(得分:162)
基于Jason Sebring的very useful tip,以及涵盖here和there的内容,我找到了一个完美的解决方案:
使用Javascript片段的伪代码:
立即在用户操作
上创建一个空白弹出窗口var importantStuff = window.open('', '_blank');
可选:添加一些“等待”信息消息。例子:
a)外部HTML页面:用
替换上面的行var importantStuff = window.open('http://example.com/waiting.html', '_blank');
b)文字:在上面的一行下面添加以下一行:
importantStuff.document.write('Loading preview...');
在准备就绪时填充内容(例如,当返回AJAX调用时)
importantStuff.location.href = 'http://shrib.com';
使用您需要的任何其他选项丰富对window.open
的调用。
我实际上使用此解决方案进行mailto重定向,它适用于我的所有浏览器(Windows 7,Android)。 _blank
位有助于mailto重定向在移动设备上运行,顺便说一句。
你的经历?有什么方法可以改善这个吗?
答案 2 :(得分:21)
此外,瑞士先生的帖子,在我的情况下, window.open 是在一个承诺内启动的,它打开了弹出窗口阻止程序,我的解决方案是: 在角度:
$scope.gotClick = function(){
var myNewTab = browserService.openNewTab();
someService.getUrl().then(
function(res){
browserService.updateTabLocation(res.url, myNewTab);
}
);
};
browserService:
this.openNewTab = function(){
var newTabWindow = $window.open();
return newTabWindow;
}
this.updateTabLocation = function(tabLocation, tab) {
if(!tabLocation){
tab.close();
}
tab.location.href = tabLocation;
}
这是使用promise响应打开新选项卡而不是调用弹出窗口阻止程序的方法。
答案 3 :(得分:17)
作为一种好的做法,我认为如果弹出窗口被阻止并且采取行动以及测试是个好主意。您需要知道window.open有一个返回值,如果操作失败,该值可能为null。例如,在以下代码中:
function pop(url,w,h) {
n=window.open(url,'_blank','toolbar=0,location=0,directories=0,status=1,menubar=0,titlebar=0,scrollbars=1,resizable=1,width='+w+',height='+h);
if(n==null) {
return true;
}
return false;
}
如果弹出窗口被阻止,window.open将返回null。所以函数将返回false。
例如,假设直接从任何链接调用此函数 使用
target="_blank"
:如果弹出窗口成功打开,则返回false
将阻止链接操作,否则如果弹出窗口被阻止, 返回true
将允许默认行为(打开新的_blank 窗口)继续。
<a href="http://whatever.com" target="_blank" onclick='return pop("http://whatever.com",300,200);' >
这样,如果有效,你会有一个弹出窗口,如果是的话,你会有一个_blank窗口 不
如果弹出窗口未打开,您可以:
答案 4 :(得分:8)
http://code.google.com/p/google-api-javascript-client/wiki/Authentication
查看其所在的区域:
设置身份验证
客户端的OAuth 2.0实现使用弹出窗口提示用户登录并批准该应用程序。对gapi.auth.authorize的第一次调用可以触发弹出窗口阻止程序,因为它会间接打开弹出窗口。要防止弹出窗口阻止程序在auth调用时触发,请在客户端加载时调用gapi.auth.init(回调)。当库准备好进行auth调用时,将执行提供的回调。
我猜它与上面的真实答案有关,它如何解释是否有立即响应,它不会触发弹出警报。 &#34; gapi.auth.init&#34;正在制作它,以便api立即发生。
实际应用
我在npm上使用节点护照和每个提供商的各种护照包制作了一个开源认证微服务。我对第三方使用了标准的重定向方法,为其提供了一个重定向网址。这是程序化的,所以我可以有不同的地方重定向到登录/注册和特定页面。
答案 5 :(得分:1)
我的用例:在我的应用中,用户单击后,将对后端执行API调用。根据响应,打开新标签页,并将api响应作为参数添加到新标签页URL(在同一域中)。
在我的用例中,唯一需要注意的是,接收API响应需要花费更多的时间1秒。因此,在新标签页中打开URL时,弹出窗口阻止程序就会显示(如果处于活动状态)。
为避免上述问题,下面是示例代码,
var new_tab=window.open()
axios.get('http://backend-api').then(response=>{
const url="http://someurl"+"?response"
new_tab.location.href=url;
}).catch(error=>{
//catch error
})
摘要:创建一个空选项卡(如第1行上方所示),并在完成API调用后,可以用网址填充该选项卡,并跳过弹出窗口阻止程序。
答案 6 :(得分:0)
除非回调成功返回,否则我不想创建新页面,所以我这样做模拟用户点击:
function submitAndRedirect {
apiCall.then(({ redirect }) => {
const a = document.createElement('a');
a.href = redirect;
a.target = '_blank';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
}
答案 7 :(得分:0)
我尝试了多种解决方案,但他是唯一一款在所有浏览器中真正适用于我的解决方案
Month Count_Date1 Count_Date2
Jan 0 2
Feb 0 1
July 1 1
Aug 2 0
Sep 3 9
答案 8 :(得分:-4)
摆脱这种情况的最简单方法是:
前:
<script>
function loadUrl(location)
{
this.document.location.href = location;
}</script>
<div onclick="loadUrl('company_page.jsp')">Abc</div>
这对我来说非常有效。 干杯