Facebook Callback hängt ‘# _ = _’ an die URL an

Der Facebook-callback hat begonnen, #_=_ Hash-Unterstrich an die Rückgabe-URL anzuhängen

Weiß jemand warum? Was ist die Lösung?

via Facebook’s Plattform Updates :

Ändern des Sitzungsumleitungsverhaltens

In dieser Woche haben wir damit begonnen, ein Fragment # ____ = ____ zum redirect_uri hinzuzufügen, wenn dieses Feld leer ist. Stellen Sie sicher, dass Ihre App mit diesem Verhalten umgehen kann.

Um das zu verhindern, setze die redirect_uri in deiner Login URL Anfrage wie folgt: (mit Facebook php-sdk)

 $facebook->getLoginUrl(array('redirect_uri' => $_SERVER['SCRIPT_URI'],'scope' => 'user_about_me')); 

AKTUALISIEREN

Das obige ist genau so, wie es in der Dokumentation steht, um das zu beheben. Die dokumentierte Lösung von Facebook funktioniert jedoch nicht. Bitte denken Sie darüber nach, einen Kommentar im Blog-Post zu Facebook Platform Updates zu hinterlassen und folgen Sie diesem Fehler , um eine bessere Antwort zu erhalten. Bis dahin fügen Sie Ihrem head-Tag Folgendes hinzu, um dieses Problem zu beheben:

  

Oder eine detailliertere Alternative (Danke Niftyletuce ):

  

TL; DR

 if (window.location.hash == '#_=_'){ history.replaceState ? history.replaceState(null, null, window.location.href.split('#')[0]) : window.location.hash = ''; } 

Vollversion mit schrittweisen Anleitungen

 // Test for the ugliness. if (window.location.hash == '#_=_'){ // Check if the browser supports history.replaceState. if (history.replaceState) { // Keep the exact URL up to the hash. var cleanHref = window.location.href.split('#')[0]; // Replace the URL in the address bar without messing with the back button. history.replaceState(null, null, cleanHref); } else { // Well, you're on an old browser, we can get rid of the _=_ but not the #. window.location.hash = ''; } } 

Schritt für Schritt:

  1. Wir kommen nur in den Codeblock, wenn das fragment #_=_ .
  2. Überprüfen Sie, ob der Browser die HTML5-Methode window.replaceState unterstützt.
    1. Bereinige die URL, indem du auf # und nur den ersten Teil nimmst.
    2. Tell history , um den aktuellen Seitenstatus durch die bereinigte URL zu ersetzen. Dies ändert den aktuellen Verlaufseintrag, anstatt einen neuen zu erstellen. Das bedeutet, dass die Vor- und Zurück-Tasten genau so funktionieren, wie Sie es möchten. 😉
  3. Wenn der Browser die HTML 5-History-Methoden nicht unterstützt, bereinigen Sie die URL so gut wie möglich, indem Sie den Hashwert auf eine leere Zeichenfolge setzen. Dies ist ein schlechtes Fallback, da es immer noch einen abschließenden Hash (example.com/#) hinterlässt und auch einen Verlaufseintrag hinzufügt, so dass die Zurück-Schaltfläche zurück zu #_-_ .

Erfahren Sie mehr über history.replaceState .

Erfahren Sie mehr über window.location .

wenn Sie die restlichen “#” aus der URL entfernen möchten

 $(window).on('load', function(e){ if (window.location.hash == '#_=_') { window.location.hash = ''; // for older browsers, leaves a # behind history.pushState('', document.title, window.location.pathname); // nice and clean e.preventDefault(); // no page reload } }) 

Dies wurde von Facebook aus Sicherheitsgründen implementiert. Hier ist die Erklärung von Eric Osgood, einem Facebook-Teammitglied:

Dies wurde als “von Entwurf” gekennzeichnet, da es eine potenzielle Sicherheitslücke verhindert.

Einige Browser fügen das Hash-Fragment von einer URL an das Ende einer neuen URL an, an die sie weitergeleitet wurden (wenn diese neue URL selbst kein Hash-Fragment hat).

Wenn beispielsweise example1.com eine Weiterleitung an example2.com zurückgibt, wird ein Browser, der zu example1.com # abc geht, zu example2.com # abc wechseln, und der Hash-Fragment-Inhalt von example1.com wäre für ein Skript in example2 zugänglich .com.

Da es möglich ist, eine Authentifizierungsflussumleitung zu einer anderen zu haben, wäre es möglich, sensible Authentifizierungsdaten von einer App zu einer anderen zugänglich zu machen.

Dies wird durch Anhängen eines neuen Hash-Fragments an die Umleitungs-URL gemildert, um dieses Browserverhalten zu verhindern.

Wenn die Ästhetik oder das clientseitige Verhalten der resultierenden URL von Belang ist, wäre es möglich, window.location.hash (oder sogar eine eigene serverseitige Weiterleitung) zu verwenden, um die anstößigen Zeichen zu entfernen.

Quelle: https://developers.facebook.com/bugs/318390728250352/

Ich bin mir nicht sicher, warum sie das tun, aber Sie können das umgehen, indem Sie den Hash oben auf Ihrer Seite zurücksetzen:

 if (window.location.hash == "#_=_") window.location.hash = ""; 

Facebook verwendet einen Rahmen und in ihm funktioniert alles mit AJAX-Kommunikation. Das größte Problem in diesem Fall ist das Beibehalten des aktuellen Seitenstatus. Soweit ich weiß, hat sich Facebook entschieden, simulierte Anker zu verwenden. Das heißt, wenn Sie irgendwo geklickt haben, simulieren sie das als Anker innerhalb Ihrer Seite, und wenn die AJAX-Kommunikation startet, ändern sie auch das Anker-Bit Ihrer URL.

Diese Lösung hilft Ihnen normalerweise, wenn Sie versuchen, die Seite neu zu laden (nicht ENTER, drücken Sie F5 ), da Ihr Browser die gesamte URL mit Ankern an den Facebook-Server sendet. Deshalb holt Facebook den letzten Stand (was Sie sehen) ab und Sie können von dort aus weiter machen.

Wenn der callback mit #_=_ , bedeutet dies, dass die Seite sich in ihrem Grundzustand befand, bevor sie verlassen wurde. Da dieser Anker vom Browser analysiert wird, müssen Sie sich nicht darum kümmern.

Sie können auch einen eigenen Hash für den redirect_uri Parameter für den Facebook-callback festlegen, der unter bestimmten Umständen hilfreich sein kann, z. B. /api/account/callback#home . Wenn Sie zurückgeleitet werden, ist es zumindest ein Hash, der einer bekannten Route entspricht, wenn Sie backbone.js oder ähnliches verwenden (nicht sicher über jquery mobile).

Major nervig, vor allem für Apps, die den URI analysieren und nicht nur das $ _GET lesen … Hier ist der Hack, den ich zusammen geworfen habe … Viel Spaß!

      URI should be clean   

Dies kann zu einem ernsten Problem werden, wenn Sie ein JS-Framework mit Hashbang (/ #! /) URLs verwenden, zB Angular. In der Tat wird Angular URLs mit einem Nicht-Hashbang-Fragment als ungültig betrachten und einen Fehler ausgeben:

 Error: Invalid url "http://example.com/#_=_", missing hash prefix "#!". 

Wenn Sie in einem solchen Fall sind (und zu Ihrem Domain-Root weiterleiten), anstatt Folgendes zu tun:

 window.location.hash = ''; // goes to /#, which is no better 

Mach einfach:

 window.location.hash = '!'; // goes to /#!, which allows Angular to take care of the rest 

Ich sehe nicht, wie dieses Problem mit Facebook AJAX verwandt ist. Tatsächlich tritt das Problem auch bei deaktivierten JavaScript- und rein Redirect-basierten Logins auf.

Ein Beispielaustausch mit Facebook:

 1. GET  RESPONSE 302 Found Location:  2. GET  RESPONSE 302 Found MY_REDIRECT_URL?code=FB_CODE#_ 3. GET MY_REDIRECT_URL?code=FB_CODE#_ 

Passiert nur mit Firefox auch für mich.

Das Hinzufügen zu meiner Weiterleitungsseite hat das Problem für mich behoben …

 if (window.location.href.indexOf('#_=_') > 0) { window.location = window.location.href.replace(/#.*/, ''); } 

Mit winkligen und eckigen ui Router können Sie das beheben

  app.config(function ($stateProvider, $urlRouterProvider, $locationProvider) { // Make a trailing slash optional for all routes // - Note: You'll need to specify all urls with a trailing slash if you use this method. $urlRouterProvider.rule(function ($injector, $location) { /*** Angular misbehaves when the URL contains a "#_=_" hash. From Facebook: Change in Session Redirect Behavior This week, we started adding a fragment #_=_ to the redirect_uri when this field is left blank. Please ensure that your app can handle this behavior. Fix: http://stackoverflow.com/questions/7131909/facebook-callback-appends-to-return-url#answer-7297873 ***/ if ($location.hash() === '_=_'){ $location.hash(null); } var path = $location.url(); // check to see if the path already has a slash where it should be if (path[path.length - 1] === '/' || path.indexOf('/?') > -1) { return; } else if (path.indexOf('?') > -1) { $location.replace().path(path.replace('?', '/?')); } else { $location.replace().path(path + '/'); } }); // etc ... }); }); 

In letzter Zeit wurde eine Änderung in der Art und Weise vorgenommen, wie Facebook Sitzungsweiterleitungen behandelt. Siehe “Änderung des Redirect-Verhaltens der Sitzung” im Blogbeitrag ” Operation Developer Love ” dieser Woche für die Ankündigung.

Für mich mache ich JavaScript-Umleitung auf eine andere Seite, um #_=_ loszuwerden. Die folgenden Ideen sollten funktionieren. 🙂

 function redirect($url){ echo ""; } 

Ein Workaround, der für mich funktionierte (mit Backbone.js), bestand darin, “# /” am Ende der an Facebook übermittelten Weiterleitungs-URL hinzuzufügen. Facebook behält das bereitgestellte Fragment und fügt kein eigenes “_ = _” an.

Bei der Rückkehr entfernt Backbone den “# /” Teil. Für AngularJS, Anhängen “#!” an die Rückgabe-URL sollte funktionieren.

Beachten Sie, dass die Fragmentkennung der ursprünglichen URL bei der Umleitung (über die HTTP-Statuscodes 300, 301, 302 und 303) von den meisten Browsern beibehalten wird, es sei denn, die Weiterleitungs-URL enthält auch eine Fragmentkennung. Dies scheint ein empfohlenes Verhalten zu sein .

Wenn Sie ein Handlerscript verwenden, das den Benutzer an eine andere Stelle weiterleitet, können Sie an die Weiterleitungs-URL “#” anhängen, um die Fragmentkennung durch eine leere Zeichenfolge zu ersetzen.

Ich weiß, dass diese Antwort zu spät ist, aber wenn Sie Passpjs verwenden, möchten Sie dies vielleicht sehen.

 return (req, res, next) => { console.log(req.originalUrl); next(); }; 

Ich habe diese Middleware geschrieben und angewendet, um die Serverinstanz auszudrücken, und die ursprüngliche URL, die ich habe, ist ohne das "#_=_" . Sieht so aus, als wenn wir die Instanz von passporJS als Middleware auf die Serverinstanz anwenden, diese Zeichen nicht, sondern nur in der Adressleiste unserer Browser sichtbar sind.

Ich benutze diese, um auch das # Symbol zu löschen.

  

Mit Angular 2 (RC5) und Hash-basierten Routen mache ich das:

 const appRoutes: Routes = [ ... {path: '_', redirectTo: '/facebookLoginSuccess'}, ... ] 

und

 export const routing = RouterModule.forRoot(appRoutes, { useHash: true }); 

Soweit ich verstehe, wird das Zeichen = in der Route als Teil der optionalen Routenparameterdefinition interpretiert (siehe https://angular.io/docs/ts/latest/guide/router.html#!#optional-route-parameters ), also nicht an der Routenanpassung beteiligt.

Für PHP SDK Benutzer

Ich habe das Problem einfach behoben, indem ich den zusätzlichen Teil vor der Weiterleitung entfernt habe.

  $loginURL = $helper->getLoginUrl($redirectURL, $fbPermissions); $loginURL = str_replace("#_=_", "", $loginURL); header("Location: " . $loginURL);