it-swarm-es.com

La devolución de llamada de Facebook agrega '# _ = _' a la URL de retorno

La devolución de llamada de Facebook comenzó a añadir #_=_ subrayado a la URL de retorno

¿Alguien sabe por qué? ¿Cuál es la solución?

453
zing ming

a través de Actualizaciones de la plataforma de Facebook :

Cambio en el comportamiento de redireccionamiento de sesión

Esta semana, comenzamos a agregar un fragmento # ____ = ____ a redirect_uri cuando este campo se deja en blanco. Por favor, asegúrese de que su aplicación puede manejar este comportamiento.

Para evitar esto, establezca el redirect_uri en su solicitud de url de inicio de sesión de este modo: (usando Facebook php-sdk)

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

ACTUALIZACIÓN

Lo anterior es exactamente como el documentación dice para solucionar este problema. Sin embargo, la solución documentada de Facebook no funciona. Considere dejar un comentario en la publicación de blog de actualizaciones de la plataforma de Facebook y siga este error para obtener una mejor respuesta. Hasta entonces, agregue lo siguiente a su etiqueta de cabecera para resolver este problema:

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

O una alternativa más detallada (gracias 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>
231
Ryan

TL; DR

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

Versión completa con instrucciones paso a paso

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

    }

}

Paso a paso:

  1. Solo entraremos en el bloque de código si fragment es #_=_.
  2. Compruebe si el navegador admite el método HTML5 window.replaceState.
    1. Limpie la URL dividiendo en # y tomando solo la primera parte.
    2. Dígale a history que reemplace el estado de la página actual con la URL limpia. Esto modifica la entrada del historial actual en lugar de crear una nueva. Lo que esto significa es que los botones de avance y retroceso funcionarán de la forma que desee. ;-)
  3. Si el navegador no admite los impresionantes métodos de historial de HTML 5, simplemente limpie la URL lo mejor que pueda estableciendo el hash en una cadena vacía. Esta es una mala alternativa porque todavía deja un hash al final (example.com/#) y también agrega una entrada de historial, por lo que el botón Atrás lo regresará a #_-_.

Obtenga más información sobre history.replaceState .

Obtenga más información sobre window.location .

104
PapaSierra

si desea eliminar el "#" restante de la 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

Esto fue implementado por Facebook por diseño por razones de seguridad. Aquí está la explicación de Eric Osgood, un miembro del equipo de Facebook:

Esto se ha marcado como "por diseño" porque evita una vulnerabilidad de seguridad potencial.

Algunos navegadores agregarán el fragmento de hash de una URL al final de una nueva URL a la que se han redirigido (si esa nueva URL no tiene un fragmento de hash).

Por ejemplo, si example1.com devuelve una redirección a example2.com, entonces un navegador que vaya a example1.com # abc irá a example2.com # abc, y el contenido del fragmento hash de example1.com sería accesible a una secuencia de comandos en example2 .com.

Dado que es posible tener un flujo de autenticación redirigido a otro, sería posible tener datos confidenciales de autenticación de una aplicación accesibles a otra.

Esto se mitiga agregando un nuevo fragmento de hash a la URL de redireccionamiento para evitar el comportamiento de este navegador.

Si la estética, o el comportamiento del lado del cliente, de la URL resultante son preocupantes, sería posible usar window.location.hash (o incluso un redireccionamiento del lado del servidor) para eliminar los caracteres ofensivos.

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

35
Mark Murphy

No estoy seguro de por qué están haciendo esto, pero puede solucionarlo restableciendo el hash en la parte superior de su página:

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

También puede especificar su propio hash en el parámetro redirect_uri para la devolución de llamada de Facebook, lo que podría ser útil en ciertas circunstancias, por ejemplo. /api/account/callback#home. Cuando vuelvas a dirigirte, al menos será un hash que corresponde a una ruta conocida si estás usando backbone.js o similar (no estoy seguro de jquery mobile).

9
pkiddie

Muy molesto, especialmente para aplicaciones que analizan el URI y no solo leen $ _GET ... Aquí está el truco que tiré juntos ... ¡Disfrútalo!

<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 un marco y en su interior todo funciona mediante la comunicación AJAX. El mayor problema en este caso es preservar el estado de la página actual. Por lo que entiendo, Facebook decidió utilizar anclajes simulados. Esto significa que si hizo clic en algún lugar, simularán eso como un ancla dentro de su página y, cuando se inicie la comunicación AJAX, también cambiarán el bit de ancla de su URL.

Esta solución le ayuda normalmente cuando intenta recargar la página (no ENTER, presione F5), porque su navegador envía la URL completa con anclajes al servidor de Facebook. Por lo tanto, Facebook recoge el último estado (lo que ve) y luego puede continuar desde allí.

Cuando la devolución de llamada regresa con #_=_ significa que la página estaba en su estado básico antes de abandonarla. Debido a que el navegador analiza este ancla, no debe preocuparse por ello.

8
Sándor Tóth

Esto puede convertirse en un problema grave si está utilizando un marco JS con URL de hashbang (/ #! /), Por ejemplo. Angular. De hecho, Angular considerará las URL con un fragmento no hashbang como no válido y generará un error:

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

Si estás en tal caso (y redireccionando a la raíz de tu dominio), en lugar de hacerlo:

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

Simplemente haz:

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

No veo cómo este problema está relacionado con facebook AJAX. De hecho, el problema también se produce con JavaScript deshabilitado y redirigido puramente los inicios de sesión basados.

Un ejemplo de intercambio 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#_  

Sucede solo con Firefox para mí también.

5
Sebastian Tusk

Agregar esto a mi página de redirección solucionó el problema para mí ...

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

Con el enrutador ui angular y angular, puedes arreglar esto

    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

Si está utilizando vue-router, puede adjuntarlo a la lista de rutas:

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

Recientemente se introdujo un cambio en la forma en que Facebook maneja los redireccionamientos de sesión. Consulte "Cambio en el comportamiento de la redirección de sesión" en la publicación de esta semana Operation Developer Love blog para el anuncio.

2
Dhiren Patel

Para mí, hago redirección de JavaScript a otra página para deshacerme de #_=_. Las siguientes ideas deberían funcionar. :)

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

Yo uso este, para eliminar el símbolo '#' también.

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

Sé que esta respuesta es tarde, pero si está utilizando passportjs, es posible que desee ver esto.

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

Escribí este middleware y lo apliqué a la instancia de Express Server, y la URL original que tengo es sin el "#_=_". Parece que cuando aplicamos la instancia de passporJS como middleware a la instancia del servidor, no toma esos caracteres, pero solo son visibles en la barra de direcciones de nuestros navegadores.

1
Krishna

Una solución que funcionó para mí (usando Backbone.js), fue agregar "# /" al final de la URL de redireccionamiento que se pasó a Facebook. Facebook conservará el fragmento proporcionado y no agregará su propio "_ = _".

Al regresar, Backbone eliminará la parte "# /". Para AngularJS, agregando "#!" a la URL de retorno debería funcionar.

Tenga en cuenta que la mayoría de los exploradores conservan el identificador de fragmento de la URL original en la redirección (a través de los códigos de estado HTTP 300, 301, 302 y 303), a menos que la URL de redireccionamiento también tenga un identificador de fragmento. Este parece ser el comportamiento recomendado .

Si usa un script de controlador que redirige al usuario a otra parte, puede agregar "#" a la URL de redirección aquí para reemplazar el identificador del fragmento con una cadena vacía.

1
Ivo Smits

Para PHP usuarios de SDK

Solucioné el problema simplemente quitando la pieza extra antes de reenviar.

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

Utilizando Angular 2 (RC5) y rutas basadas en hash, hago esto:

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

y

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

Por lo que entiendo, el carácter = en la ruta se interpreta como parte de la definición de parámetros de ruta opcional (consulte https://angular.io/docs/ts/latest/guide/router.html#!#optional-route -parámetros ), por lo que no participa en la coincidencia de rutas.

0
rcomblen

Esto eliminaría los caracteres añadidos a tu url.

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