web-dev-qa-db-ja.com

ブラウザのポップアップブロッカーを避ける

私はOAuth認証フローを純粋にJavaScriptで開発しており、ポップアップで「許可アクセス」ウィンドウをユーザーに表示したいのですが、ブロックされます。

window.openまたはwindow.showModalDialogによって作成されたポップアップウィンドウが、異なるブラウザーのポップアップブロッカーによってブロックされるのを防ぐにはどうすればよいですか?

147
Pablo Fernandez

一般的なルールは、window.openなどが直接的なユーザーアクションによって呼び出されないjavascriptから呼び出された場合、ポップアップブロッカーが関与することです。つまり、ボタンのクリックに応答して、ポップアップブロッカーにヒットすることなくwindow.openを呼び出すことができますが、タイマーイベントに同じコードを配置するとブロックされます。コールチェーンの深さも要因です。一部の古いブラウザは直接の呼び出し元のみを見るため、新しいブラウザは少し遡って呼び出し元の呼び出し元がマウスクリックなどであったかどうかを確認できます。

259
dthorpe

Jason Sebring非常に役立つヒント に基づいており、 here および there に含まれているものに基づいて、私の場合の完璧なソリューション:

JavaScriptスニペットを使用した擬似コード:

  1. ユーザーアクションですぐに空白のポップアップを作成する

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

    オプション:「待機」情報メッセージを追加します。例:

    a)外部HTMLページ:上記の行を

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

    b)テキスト:上記の下に次の行を追加します。

    importantStuff.document.write('Loading preview...');
    
  2. 準備ができたら(たとえば、AJAX呼び出しが返されたとき)、コンテンツで埋めます

    importantStuff.location.href = 'http://shrib.com';
    

必要な追加オプションを使用して、window.openへの呼び出しを充実させます。

実際にこのソリューションをmailtoリダイレクトに使用し、すべてのブラウザー(Windows 7、Android)で機能します。 _blankビットは、mailtoリダイレクトがモバイルで機能するのに役立ちます(ところで)。

あなたの経験は?これを改善する方法はありますか?

163
Swiss Mister

さらに、スイスミスターの投稿では、私の場合、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応答を使用して、ポップアップブロッカーを呼び出さずに新しいタブを開く方法です。

21
David

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のノードパスポートと各プロバイダーのさまざまなパスポートパッケージを使用して、オープンソース認証マイクロサービスを作成しました。サードパーティへの標準リダイレクトアプローチを使用して、サードパーティにリダイレクトURLを提供しました。これはプログラム的なものだったので、ログイン/サインアップや特定のページにリダイレクトするためのさまざまな場所を確保できました。

github.com/sebringj/ath

passportjs.org

8
Jason Sebring

コールバックが正常に返されない限り、新しいページを作成したくなかったので、これをsimulateをクリックしてユーザーがクリックしました。

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

私は複数のソリューションを試しましたが、すべてのブラウザで実際に働いたのは彼だけです

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

0
pomobc