it-swarm.com.de

Vermeiden Sie Browser-Popup-Blocker

Ich entwickle einen OAuth-Authentifizierungsfluss ausschließlich in JavaScript, und ich möchte dem Benutzer das Fenster "Zugriff gewähren" in einem Popup anzeigen, es wird jedoch blockiert.

Wie kann ich verhindern, dass Popup-Fenster, die von window.open oder window.showModalDialog erstellt wurden, von den Popup-Blockern der verschiedenen Browser blockiert werden?

139
Pablo Fernandez

Die allgemeine Regel lautet, dass Popup-Blocker aktiviert werden, wenn window.open oder ähnliches von Javascript aufgerufen wird, das nicht von direkter Benutzeraktion aufgerufen wird. Das heißt, Sie können window.open als Reaktion auf einen Schaltflächenklick aufrufen, ohne vom Popup-Blocker getroffen zu werden. Wenn Sie jedoch denselben Code in ein Timer-Ereignis einfügen, wird er blockiert. Die Tiefe der Anrufkette ist auch ein Faktor - einige ältere Browser betrachten nur den unmittelbaren Anrufer, neuere Browser können ein wenig zurückverfolgen, um zu sehen, ob der Anrufer des Anrufers ein Mausklick war usw. Halten Sie es so flach wie möglich, um Popup-Blocker zu vermeiden.

248
dthorpe

Basierend auf Jason Sebring 's sehr nützlicher Tipp , und auf den verarbeiteten Sachen hier und da habe ich eine perfekte Lösung für meinen Fall gefunden:

Pseudo-Code mit Javascript-Ausschnitten:

  1. erstellen Sie sofort ein leeres Popup für die Benutzeraktion

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

    Optional: Fügen Sie eine "wartende" Informationsnachricht hinzu. Beispiele:

    a) Eine externe HTML-Seite: Ersetzen Sie die obige Zeile durch

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

    b) Text: Fügen Sie die folgende Zeile unterhalb der obigen ein:

    importantStuff.document.write('Loading preview...');
    
  2. füllen Sie es mit Inhalt, wenn es fertig ist (wenn z. B. der Aufruf von AJAX zurückgegeben wird)

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

Bereichern Sie den Aufruf an window.open mit den zusätzlichen Optionen, die Sie benötigen.

Ich verwende diese Lösung tatsächlich für eine Mailto-Umleitung, und sie funktioniert auf allen meinen Browsern (Windows 7, Android). Das _blank-Bit hilft der Mailto-Umleitung, um auf dem Handy zu arbeiten, übrigens.

Deine Erfahrung? Irgendwelche Möglichkeiten, dies zu verbessern?

153
Swiss Mister

Ausser schweizer Herr Post, in meinem Fall das window.open wurde innerhalb eines Versprechens gestartet, das den Popup-Blocker einschaltete.

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

so können Sie eine neue Registerkarte mit der Promise-Antwort öffnen und den Popup-Blocker nicht aufrufen.

19
David

Als bewährte Methode halte ich es für eine gute Idee, zu testen , ob ein Popup blockiert wurde und gegebenenfalls Maßnahmen zu ergreifen. Sie müssen wissen, dass window.open einen Rückgabewert hat, und dieser Wert kann null sein, wenn die Aktion fehlgeschlagen ist. Zum Beispiel im folgenden Code:

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

wenn das Popup blockiert ist, gibt window.open null zurück. Die Funktion gibt also false zurück.

Stellen Sie sich zum Beispiel vor, Sie rufen diese Funktion direkt von einem beliebigen Link aus auf with target="_blank": Wenn das Popup erfolgreich geöffnet wurde, wird .__ zurückgegeben. false blockiert die Verknüpfungsaktion, andernfalls, wenn das Popup blockiert ist, Wenn Sie true zurückgeben, wird das Standardverhalten (neues _blank -Fenster öffnen) geöffnet und fortgesetzt.

<a href="http://whatever.com" target="_blank" onclick='return pop("http://whatever.com",300,200);' >

Auf diese Weise haben Sie ein Popup, wenn es funktioniert, und ein _blank-Fenster, wenn nicht.

Wenn sich das Popup nicht öffnet, können Sie:

  • Öffnen Sie ein leeres Fenster wie im Beispiel und machen Sie weiter
  • ein falsches Popup öffnen (ein iframe auf der Seite)
  • den Benutzer informieren ("Bitte erlauben Sie Popups für diese Site")
  • Öffnen Sie ein leeres Fenster und informieren Sie den Benutzer etc ..
16
FrancescoMM

von Google oauth JavaScript API:

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

Sehen Sie den Bereich, in dem es steht:

Authentifizierung einrichten

Die Client-Implementierung von OAuth 2.0 verwendet ein Popup-Fenster, um den Benutzer zur Anmeldung aufzufordern und die Anwendung zu genehmigen. Der erste Aufruf von gapi.auth.authorize kann Popup-Blocker auslösen, da das Popup-Fenster indirekt geöffnet wird. Um zu verhindern, dass der Popup-Blocker bei auth-Aufrufen ausgelöst wird, rufen Sie gapi.auth.init (callback) auf, wenn der Client geladen wird. Der bereitgestellte Rückruf wird ausgeführt, wenn die Bibliothek zum Aufruf von Auth bereit ist. 

Ich würde vermuten, dass es sich auf die eigentliche Antwort bezieht, wie es erklärt, wenn eine sofortige Antwort vorliegt, wird der Popup-Alarm nicht ausgelöst. Die "gapi.auth.init" macht es so, dass das API sofort passiert.

Praktische Anwendung

Ich habe einen Open Source-Authentifizierungs-Microservice mit Node Passport für npm und den verschiedenen Passport-Paketen für jeden Anbieter erstellt. Ich habe einen Standard-Redirect-Ansatz für den Drittanbieter verwendet und ihm eine Weiterleitungs-URL gegeben. Dies war programmatisch, so dass ich verschiedene Stellen haben könnte, an die ich mich zurückmelden kann, wenn ich mich anmelde/anmelde und auf bestimmten Seiten. 

github.com/sebringj/athu

passportjs.org

8
Jason Sebring

Ich wollte die neue Seite erst erstellen, wenn der Rückruf erfolgreich zurückgegeben wurde. Daher habe ich Folgendes getan, um simulieren den Benutzer zu klicken:

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

Ich habe mehrere Lösungen ausprobiert, aber er ist die einzige, die in allen Browsern tatsächlich für mich funktioniert hat

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

0
pomobc