我正在纯粹用JavaScript开发OAuth身份验证流程,我想在弹出窗口中向用户显示“授予访问权限”窗口,但该窗口被阻止了。
如何防止由window.open
或创建的弹出窗口window.showModalDialog
被不同浏览器的弹出窗口阻止程序阻止?
我正在纯粹用JavaScript开发OAuth身份验证流程,我想在弹出窗口中向用户显示“授予访问权限”窗口,但该窗口被阻止了。
如何防止由window.open
或创建的弹出窗口window.showModalDialog
被不同浏览器的弹出窗口阻止程序阻止?
Answers:
一般规则是,如果window.open
不是直接用户操作调用的javascript调用了javascript或类似方法,则会阻止弹出窗口阻止程序。也就是说,您可以window.open
响应单击按钮而调用,而不会被弹出窗口阻止程序击中,但是如果将相同的代码放入计时器事件中,它将被阻止。呼叫链深度也是一个因素-一些较旧的浏览器仅查看直接呼叫者,较新的浏览器可以稍微回溯以查看呼叫者的呼叫者是否是鼠标单击等。请使其尽可能浅,以避免弹出窗口阻止程序。
基于Jason Sebring的非常有用的技巧,以及在这里和那里所涉及的内容,我为我的案例找到了一个完美的解决方案:
带有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重定向在移动设备btw上工作。
你的经验?有什么办法可以改善?
Whatever it is you intend to do, there is a better way than a popup window
大声笑?奇怪的概括。客户希望他们通过身份验证的页面保持打开状态,并希望通过身份验证后的新站点/登录页面在新选项卡中打开。是的,不是我关于出色的用户体验的想法……但这似乎是合理的
importantStuff.close
以关闭新选项卡,并在原始页面中提供并发出警报。
除了瑞士先生的帖子,在我的情况下,window.open是在promise中启动的,它打开了弹出窗口阻止程序,我的解决方案是:
$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响应而不调用弹出窗口阻止程序来打开新选项卡的方法。
const tab = window.open(); observable.subscribe(dataUrl => tab.location.href = dataUrl);
.then
当时的答案,这就是为什么我如此困惑的原因:/ SRY ...
作为一个好的实践,我认为最好测试弹出窗口是否被阻止并采取措施以防万一。您需要知道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"
:如果成功打开了弹出窗口,则returnfalse
将阻止链接操作,否则,如果弹出窗口被阻止,则returntrue
将让默认行为(打开新的_blank窗口)并继续。
<a href="http://whatever.com" target="_blank" onclick='return pop("http://whatever.com",300,200);' >
这样,您将有一个弹出窗口(如果可以),以及一个_blank窗口(如果没有)。
如果弹出窗口没有打开,您可以:
http://code.google.com/p/google-api-javascript-client/wiki/Authentication
查看读取的区域:
设置身份验证
OAuth 2.0的客户端实现使用弹出窗口提示用户登录并批准该应用程序。第一次调用gapi.auth.authorize可以触发弹出窗口阻止程序,因为它间接打开了弹出窗口。为防止弹出窗口阻止程序在auth调用上触发,请在客户端加载时调用gapi.auth.init(callback)。库准备好进行身份验证调用时,将执行提供的回调。
我猜想它与上面的真实答案有关,它解释了如果有立即响应,它将不会触发弹出警报。“ gapi.auth.init”正在制作,因此api立即发生。
实际应用
我使用npm上的节点通行证以及每个提供商的各种通行证软件包制作了一个开源身份验证微服务。我对第三方使用了一种标准的重定向方法,为它提供了重定向URL以供返回。这是编程式的,因此在登录/注册时以及在特定页面上,我可以有不同的位置重定向回。
我尝试了多种解决方案,但他是所有浏览器中唯一对我有效的解决方案
let newTab = window.open();
newTab.location.href = url;
url
?它没有分配。
http://example.com
window.open()
无法以编程方式打开新窗口,如果需要,该答案是选项之一。使用newTab
我们引用的变量window.open()
,以后我们可以调用它,插入url
我们需要的变量(在我的情况下为某些blob的url),新选项卡将在输入的url上打开。
除非回调成功返回,否则我不想创建新页面,因此我这样做是为了模拟用户单击:
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);
});
}
摆脱这种情况的最简单方法是:
例如:
<script>
function loadUrl(location)
{
this.document.location.href = location;
}</script>
<div onclick="loadUrl('company_page.jsp')">Abc</div>
这对我来说非常有效。干杯