我正在开发一个纯JavaScript的OAuth身份验证流程,我想在弹出窗口中向用户显示“授予访问权限”窗口,但它被阻塞了。
我如何防止弹出窗口创建的任何窗口。打开或打开窗户。showModalDialog从被不同的浏览器的弹出窗口拦截器阻止?
我正在开发一个纯JavaScript的OAuth身份验证流程,我想在弹出窗口中向用户显示“授予访问权限”窗口,但它被阻塞了。
我如何防止弹出窗口创建的任何窗口。打开或打开窗户。showModalDialog从被不同的浏览器的弹出窗口拦截器阻止?
The general rule is that popup blockers will engage if window.open or similar is invoked from javascript that is not invoked by direct user action. That is, you can call window.open in response to a button click without getting hit by the popup blocker, but if you put the same code in a timer event it will be blocked. Depth of call chain is also a factor - some older browsers only look at the immediate caller, newer browsers can backtrack a little to see if the caller's caller was a mouse click etc. Keep it as shallow as you can to avoid the popup blockers.
从谷歌的oauth JavaScript API:
http://code.google.com/p/google-api-javascript-client/wiki/Authentication
请看上面写着:
设置认证
OAuth 2.0的客户端实现使用一个弹出窗口来提示用户登录并批准应用程序。第一次调用gapi.auth.authorize可以触发弹出窗口拦截器,因为它间接地打开了弹出窗口。为了防止弹出窗口阻止程序在认证调用时触发,在客户端加载时调用gapi.auth.init(回调)。当库准备进行身份验证调用时,将执行提供的回调。
我猜这与上面的真实答案有关,它解释了如果有立即的反应,它不会触发弹出警报。“gapi.auth。Init使API立即发生。
实际应用
我在npm上使用节点护照和每个提供商的各种护照包创建了一个开源身份验证微服务。我使用了一个标准的重定向方法到第三方,给它一个重定向URL回来。这是程序化的,所以我可以有不同的地方重定向回如果登录/注册和特定的页面。
github.com/sebringj/athu
passportjs.org
基于Jason Sebring的非常有用的技巧,以及这里和那里覆盖的东西,我找到了一个完美的解决方案:
伪代码与Javascript片段:
immediately create a blank popup on user action var importantStuff = window.open('', '_blank'); (Enrich the call to window.open with whatever additional options you need.) Optional: add some "waiting" info message. Examples: a) An external HTML page: replace the above line with var importantStuff = window.open('http://example.com/waiting.html', '_blank'); b) Text: add the following line below the above one: importantStuff.document.write('Loading preview...'); fill it with content when ready (when the AJAX call is returned, for instance) importantStuff.location.href = 'https://example.com/finally.html'; Alternatively, you could close the window here if you don't need it after all (if ajax request fails, for example - thanks to @Goose for the comment): importantStuff.close();
我实际上使用这个解决方案进行邮件重定向,它适用于我所有的浏览器(windows 7, Android)。顺便说一下,_blank位有助于邮件重定向在移动设备上工作。
作为一个好的实践,我认为这是一个好主意,测试一个弹出窗口是否被阻止,并采取行动,以防万一。你需要了解那个窗口。Open有一个返回值,如果操作失败,该值可能为空。例如,在以下代码中:
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;
}
如果弹出窗口被阻塞,窗口。Open将返回null。所以函数会返回false。
例如,想象一下直接从任何链接调用这个函数 target="_blank":如果弹出窗口被成功打开,返回 False将阻塞链接动作,否则如果弹出窗口被阻塞, 返回true将允许默认的行为(打开新的_blank 窗口)然后继续。
<a href="http://whatever.com" target="_blank" onclick='return pop("http://whatever.com",300,200);' >
这样你就会有一个弹出窗口,如果它工作,和一个_blank窗口 不是。
如果弹出框没有打开,你可以:
像例子中那样打开一个空白窗口,然后继续 打开一个假的弹出窗口(页面内的iframe) 通知用户(“请允许本网站弹出窗口”) 打开一个空白窗口,然后通知用户 等。
摆脱这种情况最简单的方法是:
不要使用document.open()。 而是使用this.document.location.href = location;要加载的url在哪里
例:
<script>
function loadUrl(location)
{
this.document.location.href = location;
}</script>
<div onclick="loadUrl('company_page.jsp')">Abc</div>
这对我来说非常有效。 干杯
另外瑞士先生张贴,在我的情况下窗口。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;
}
这就是如何使用承诺响应而不调用弹出窗口阻止程序打开一个新选项卡。
我不想让新的页面,除非回调成功返回,所以我这样做来模拟用户点击:
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);
});
}
我尝试了多种解决方案,但他的解决方案是唯一一个在所有浏览器中都有效的解决方案
let newTab = window.open(); newtable .location.href = url;
我的用例:在我的react应用程序中,在用户单击后端执行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调用完成时,您可以用url填充选项卡并跳过弹出窗口阻止程序。
只需使用window。location。href = yourUrl或者target='_blank'的url
Window.open()有太多问题,如果距离用户操作超过一秒钟,很多浏览器会将其视为弹出窗口并阻止它
我已经通过使用setTimeOut函数来管理这一点。
setTimeOut(function(){
window.location.replace("https://www.google.com/");
}, 1000)
✅✅✅✅✅