簡體   English   中英

避免瀏覽器彈出窗口攔截器

[英]Avoid browser popup blockers

我純粹在 JavaScript 中開發 OAuth 身份驗證流程,我想在彈出窗口中向用戶顯示“授予訪問權限”window,但它被阻止了。

如何防止由window.openwindow.showModalDialog創建的彈出窗口 windows 被不同瀏覽器的彈出窗口阻止程序阻止?

一般規則是,如果window.open或類似的不是由直接用戶操作調用的 javascript 調用的,則彈出窗口阻止程序將參與。 也就是說,您可以調用window.open以響應按鈕單擊而不會被彈出窗口阻止程序擊中,但是如果您將相同的代碼放在計時器事件中,它將被阻止。 調用鏈的深度也是一個因素 - 一些較舊的瀏覽器只查看直接調用者,較新的瀏覽器可以回溯一點,看看調用者的調用者是否是鼠標點擊等。盡可能保持淺層以避免彈出窗口阻止程序。

基於Jason Sebring非常有用的提示,以及這里那里涵蓋的內容,我為我的案例找到了一個完美的解決方案:

帶有 Javascript 片段的偽代碼:

  1. 立即在用戶操作上創建一個空白彈出窗口

     var importantStuff = window.open('', '_blank');

    (使用您需要的任何其他選項豐富對window.open的調用。)

    可選:添加一些“等待”信息消息。 例子:

    a) 外部 HTML 頁面:將上面的行替換為

     var importantStuff = window.open('http://example.com/waiting.html', '_blank');

    b) 文本:在上面一行下面添加以下行:

     importantStuff.document.write('Loading preview...');
  2. 准備好時用內容填充它(例如,當返回 AJAX 調用時)

     importantStuff.location.href = 'https://example.com/finally.html';

    或者,如果您根本不需要它,您可以在此處關閉窗口(例如, if ajax request fails - 感謝@Goose 的評論):

     importantStuff.close();

我實際上將這個解決方案用於 mailto 重定向,它適用於我所有的瀏覽器(Windows 7、Android)。 _blank位有助於 mailto 重定向在移動設備上工作,順便說一句。

作為一個很好的做法,我認為測試彈出窗口是否被阻止並采取措施以防萬一是個好主意。 您需要知道 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 窗口如果沒有。

如果彈出窗口沒有打開,您可以:

  • 像示例中一樣打開一個空白窗口並繼續
  • 打開一個假彈出窗口(頁面內的 iframe)
  • 通知用戶(“請允許此站點的彈出窗口”)
  • 打開一個空白窗口,然后通知用戶等。

此外,Swiss Mister post,在我的情況下, window.open是在一個 promise 中啟動的,它打開了彈出窗口阻止程序,我的解決方案是:在 angular 中:

$scope.gotClick = function(){

  var myNewTab = browserService.openNewTab();
  someService.getUrl().then(
    function(res){
        browserService.updateTabLocation(res.url, myNewTab);

    }
  );
};

瀏覽器服務:

this.openNewTab = function(){
     var newTabWindow = $window.open();
     return newTabWindow;
}

this.updateTabLocation = function(tabLocation, tab) {
     if(!tabLocation){
       tab.close();
     }
     tab.location.href = tabLocation;
}

這就是您可以使用承諾響應而不調用彈出窗口阻止程序打開新選項卡的方法。

來自 Google 的 oauth JavaScript API:

http://code.google.com/p/google-api-javascript-client/wiki/Authentication

看到它寫的區域:

設置身份驗證

OAuth 2.0 客戶端的實現使用一個彈出窗口來提示用戶登錄並批准應用程序。 第一次調用 gapi.auth.authorize 可以觸發彈出窗口阻止程序,因為它間接打開了彈出窗口。 為了防止彈出窗口阻止程序在身份驗證調用時觸發,請在客戶端加載時調用 gapi.auth.init(callback)。 當庫准備好進行身份驗證調用時,將執行提供的回調。

我猜它與上面的真實答案有關,它如何解釋是否有立即響應,它不會觸發彈出警報。 “gapi.auth.init”正在制作它以便api立即發生。

實際應用

我使用 npm 上的節點通行證和每個提供商的各種通行證包制作了一個開源身份驗證微服務。 我對第 3 方使用了標准的重定向方法,並為其提供了一個重定向 URL 以供返回。 這是程序化的,所以如果登錄/注冊和特定頁面上,我可以有不同的地方重定向回。

github.com/sebringj/athu

護照網站

我嘗試了多種解決方案,但他是唯一一個在所有瀏覽器中真正對我有用的解決方案

let newTab = window.open(); newTab.location.href = url;

我的用例:在我的反應應用程序中,在用戶單擊時,會對后端執行 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()有太多問題,如果用戶操作超過一秒,許多瀏覽器會將其視為彈出窗口並阻止它

除非回調成功返回,否則我不想制作新頁面,所以我這樣做是為了模擬用戶點擊:

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);
  });
}

@here 我發現它在所有瀏覽器中都可以正常工作

window.open(URL) || window.location.assign(URL)

我通過使用 setTimeOut function 來管理這個。

setTimeOut(function(){
  window.location.replace("https://www.google.com/");
}, 1000)

✅✅✅✅✅

擺脫這種情況的最簡單方法是:

  1. 不要使用 document.open()。
  2. 而是使用 this.document.location.href = location; 其中 location 是要加載的 url

前任 :

<script>
function loadUrl(location)
{
this.document.location.href = location;
}</script>

<div onclick="loadUrl('company_page.jsp')">Abc</div>

這對我來說非常有效。 干杯

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM