kutombawewe.net

La richiamata di Facebook aggiunge "# _ = _" per restituire l'URL

Il callback di Facebook ha iniziato ad aggiungere #_=_ underscore all'URL di ritorno

Qualcuno sa perché? Qual'è la soluzione?

442
zing ming

via Aggiornamenti piattaforma di Facebook :

Modifica nel comportamento di reindirizzamento della sessione

Questa settimana, abbiamo iniziato ad aggiungere un frammento # ____ = ____ al redirect_uri quando questo campo è lasciato vuoto. Assicurati che la tua app sia in grado di gestire questo comportamento.

Per evitare ciò, imposta redirect_uri nella tua richiesta di url di login in questo modo: (usando Facebook php-sdk)

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

AGGIORNARE

Quanto sopra è esattamente come la documentazione dice di risolvere questo problema. Tuttavia, la soluzione documentata di Facebook non funziona. Si prega di considerare di lasciare un commento sul Post di blog di aggiornamenti della piattaforma Facebook e seguire questo bug per ottenere una risposta migliore. Fino ad allora, aggiungi il seguente tag head per risolvere questo problema:

<script type="text/javascript">
    if (window.location.hash && window.location.hash == '#_=_') {
        window.location.hash = '';
    }
</script>

O un'alternativa più dettagliata (grazie niftylettuce ):

<script type="text/javascript">
    if (window.location.hash && window.location.hash == '#_=_') {
        if (window.history && history.pushState) {
            window.history.pushState("", document.title, window.location.pathname);
        } else {
            // Prevent scrolling by storing the page's current scroll offset
            var scroll = {
                top: document.body.scrollTop,
                left: document.body.scrollLeft
            };
            window.location.hash = '';
            // Restore the scroll offset, should be flicker free
            document.body.scrollTop = scroll.top;
            document.body.scrollLeft = scroll.left;
        }
    }
</script>
229
Ryan

TL; DR

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

Versione completa con istruzioni dettagliate

// 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 = "";

    }

}

Passo dopo passo:

  1. Entreremo nel blocco di codice solo se fragment è #_=_.
  2. Verifica se il browser supporta il metodo window.replaceState di HTML5 .
    1. Pulisci l'URL dividendolo su # e prendendo solo la prima parte.
    2. Dì a history di sostituire lo stato corrente della pagina con l'URL pulito. Ciò modifica la voce della cronologia corrente invece di crearne una nuova. Ciò significa che i pulsanti Indietro e Avanti funzioneranno nel modo desiderato. ;-)
  3. Se il browser non supporta i fantastici metodi di cronologia HTML 5, ripulisci l'URL al meglio impostando l'hash sulla stringa vuota. Questo è un fallback perché lascia ancora un hash finale (esempio.com/#) e aggiunge anche una voce di cronologia, quindi il pulsante Indietro ti riporterà a #_-_

Ulteriori informazioni su history.replaceState .

Ulteriori informazioni su window.location .

99
PapaSierra

se si desidera rimuovere il "#" rimanente dall'URL

$(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
  }
})
57
likebeats

Questo è stato implementato da Facebook per motivi di sicurezza. Ecco la spiegazione di Eric Osgood, un membro del team di Facebook:

Questo è stato contrassegnato come "design" perché impedisce una potenziale vulnerabilità di sicurezza.

Alcuni browser aggiungeranno il frammento di hash da un URL alla fine di un nuovo URL a cui sono stati reindirizzati (se il nuovo URL non ha stesso ha un frammento hash).

Ad esempio se example1.com restituisce un reindirizzamento a example2.com, quindi a il browser che va a example1.com # abc andrà su example2.com # abc e il il contenuto dei frammenti di hash da example1.com sarebbe accessibile a un script su example2.com.

Poiché è possibile avere un reindirizzamento del flusso di autenticazione a un altro, esso sarebbe possibile avere dati di autenticazione sensibili da un'app accessibile ad un altro.

Questo viene mitigato aggiungendo un nuovo frammento di hash all'URL di reindirizzamento per prevenire questo comportamento del browser.

Se l'estetica, o il comportamento lato client, dell'URL risultante sono di preoccupazione, sarebbe possibile usare window.location.hash (o anche un reindirizzamento sul lato server del proprio) per rimuovere l'offendente personaggi.

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

33
Mark Murphy

Puoi anche specificare il tuo hash nel parametro redirect_uri per il callback di Facebook, che potrebbe essere utile in determinate circostanze, ad es. /api/account/callback#home. Quando si viene reindirizzati, sarà almeno un hash che corrisponde a un percorso noto se si utilizza backbone.js o simili (non si è sicuri di jquery mobile).

9
pkiddie

Major fastidioso, soprattutto per le app che analizzano l'URI e non solo per leggere $ _GET ... Ecco l'hack che ho buttato insieme ... Enjoy!

<html xmlns:fb='http://www.facebook.com/2008/fbml'>
<head>
        <script type="text/javascript">
        // Get rid of the Facebook residue hash in the URI
        // Must be done in JS cuz hash only exists client-side
        // IE and Chrome version of the hack
        if (String(window.location.hash).substring(0,1) == "#") {
                window.location.hash = "";
                window.location.href=window.location.href.slice(0, -1);
                }
        // Firefox version of the hack
        if (String(location.hash).substring(0,1) == "#") {
                location.hash = "";
                location.href=location.href.substring(0,location.href.length-3);
                }
        </script>
</head>
<body>
URI should be clean
</body>
</html>
8
Jeremy Whitt

Facebook usa una cornice e al suo interno tutto funziona con AJAX comunicazione. Il problema più grande in questo caso è la conservazione dello stato corrente della pagina. Per quanto ho capito, Facebook ha deciso di utilizzare ancore simulate. Ciò significa che se fai clic da qualche parte, lo simulano come un'ancora all'interno della tua pagina e quando inizia la comunicazione AJAX, cambiano anche il bit di ancoraggio dell'URL.

Questa soluzione ti aiuta normalmente quando tenti di ricaricare la pagina (non INVIO, premi F5), perché il tuo browser invia l'intero URL con ancore al server di Facebook. Quindi Facebook raccoglie lo stato più recente (quello che vedi) e sei quindi in grado di continuare da lì.

Quando il callback ritorna con #_=_ significa che la pagina era nel suo stato di base prima di lasciarla. Poiché questa ancora viene analizzata dal browser, non devi preoccuparti di ciò.

8
Sándor Tóth

Questo può diventare un problema serio se stai usando un framework JS con hashbang (/ #! /) URL, ad es. Angolare. Infatti, Angular considererà gli URL con un frammento non hashbang non valido e genererà un errore:

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

Se ti trovi in ​​questo caso (e ti stai reindirizzando alla tua radice di dominio), invece di fare:

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

Basta fare:

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

Non vedo come questo problema è legato a Facebook AJAX. In realtà il problema si verifica anche con JavaScript disabilitato e gli accessi basati su reindirizzamenti puramente. 

Un esempio di scambio con facebook: 

1. GET <https://www.facebook.com/dialog/oauth?client_id=MY_APP_ID&scope=email&redirect_uri=MY_REDIRECT_URL> RESPONSE 302 Found Location: <https://www.facebook.com/connect/uiserver.php?[...]>  
2. GET <https://www.facebook.com/connect/uiserver.php?[...]> RESPONSE 302 Found MY_REDIRECT_URL?code=FB_CODE#_  
3. GET MY_REDIRECT_URL?code=FB_CODE#_  

Succede solo con Firefox anche per me.

5
Sebastian Tusk

Aggiungendo questo alla mia pagina di reindirizzamento risolto il problema per me ...

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

Con il router ui angolare e angolare, è possibile risolvere questo problema 

    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 ...
    });
});
3
rebelliard

Se stai usando vue-router, puoi aggiungere all'elenco delle rotte:

{
  path: '/_=_',
  redirect: '/', // <-- or other default route
},
2
Slawomir

Recentemente è stata introdotta una modifica nel modo in cui Facebook gestisce i reindirizzamenti di sessione. Vedere "Modifica nel comportamento di reindirizzamento della sessione" nel post del blog di Operation Developer Love di questa settimana per l'annuncio.

2
Dhiren Patel

Per me, faccio il reindirizzamento JavaScript su un'altra pagina per sbarazzarmi di #_=_. Le idee qui sotto dovrebbero funzionare. :)

function redirect($url){
    echo "<script>window.location.href='{$url}?{$_SERVER["QUERY_STRING"]}'</script>";        
}
2
Eng Cy

Io uso questo, per eliminare anche il simbolo '#'.

<script type="text/javascript">
    if (window.location.hash && window.location.hash == '#_=_') {
        window.location.href = window.location.href.split('#_=_')[0];
    }
</script>
1
Simon

So che questa risposta è in ritardo, ma se utilizzi passportjs, potresti voler vedere questo. 

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

Ho scritto questo middleware e l'ho applicato per esprimere l'istanza del server, e l'URL originale che ho è senza "#_=_". Sembra che quando applichiamo l'istanza di passporJS come middleware all'istanza del server, non prende quei caratteri, ma sono visibili solo sulla barra degli indirizzi dei nostri browser. 

1
Krishna

Una soluzione che ha funzionato per me (utilizzando Backbone.js), era quella di aggiungere "# /" alla fine dell'URL di reindirizzamento passato a Facebook. Facebook manterrà il frammento fornito e non aggiungerà il proprio "_ = _".

Al ritorno, Backbone rimuoverà la parte "# /". Per AngularJS, aggiungendo "#!" all'URL di ritorno dovrebbe funzionare.

Si noti che l'identificatore di frammento dell'URL originale viene conservato al reindirizzamento (tramite i codici di stato HTTP 300, 301, 302 e 303) dalla maggior parte dei browser, a meno che l'URL di reindirizzamento abbia anche un identificatore di frammento. Questo sembra essere un comportamento raccomandato .

Se si utilizza uno script di gestione che reindirizza l'utente altrove, è possibile aggiungere "#" all'URL di reindirizzamento qui per sostituire l'identificatore di frammento con una stringa vuota.

1
Ivo Smits

Per PHP utenti SDK

Ho risolto il problema semplicemente rimuovendo la parte extra prima di inoltrare.

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

Utilizzando Angular 2 (RC5) e route basate su hash, io faccio questo:

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

e

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

Per quanto ho capito, il carattere = nella route è interpretato come parte della definizione dei parametri del percorso facoltativo (vedere https://angular.io/docs/ts/latest/guide/router.html#!#optional-route -parameters ), quindi non coinvolto nella corrispondenza del percorso.

0
rcomblen

Questo rimuoverebbe i caratteri aggiunti al tuo URL

<script type="text/javascript">
 var idx=window.location.toString().indexOf("#_=_"); 
   if (idx > 0) { 
     window.location = window.location.toString().substring(0, idx); 
   } 
</script>
0