Facebook обратный вызов добавляет '# _ = _' для возврата URL-адреса

Обратный вызов Facebook начал добавлять #_=_ хэш-символ подчеркивания к URL-адресу возврата

Кто-нибудь знает, почему? Каково решение?

Ответ 1

через Facebook Platform Updates:

Изменение поведения переадресации сеанса

На этой неделе мы начали добавлять фрагмент # ____ = ____ к redirect_uri, когда это поле остается пустым. Убедитесь, что ваше приложение может поведение.

Чтобы предотвратить это, установите redirect_uri в запросе URL-адреса вашего входа так: (используя Facebook php-sdk)

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

UPDATE

Вышеприведенная информация в точности соответствует документации. Однако документальное решение Facebook не работает. Пожалуйста, оставьте комментарий к сообщению Facebook в блоге обновлений для платформы и следуйте этой ошибке, чтобы получить лучший ответ. До тех пор, чтобы решить эту проблему, добавьте следующее в свой тег:

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

Или более подробная альтернатива (спасибо 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 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>

Ответ 2

TL; DR

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

Полная версия с пошаговыми инструкциями

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

    }

}

Шаг за шагом:

  • Мы попадаем только в блок кода, если fragment - #_=_.
  • Проверьте, поддерживает ли браузер метод HTML5 window.replaceState.
    • Очистите URL-адрес, разделив его на # и выбрав только первую часть.
    • Сообщите history, чтобы заменить текущее состояние страницы на чистый URL. Это изменяет текущую запись истории, а не создает новую. Это означает, что кнопки назад и вперед будут работать так, как вы хотите.; -)
  • Если браузер не поддерживает удивительные методы истории HTML 5, просто очистите URL как можно лучше, установив хэш в пустую строку. Это плохой запас, потому что он по-прежнему оставляет хвостовую хэш (example.com/#), а также добавляет запись истории, поэтому кнопка "Назад" вернет вас к #_-_.

Подробнее о history.replaceState.

Подробнее о window.location.

Ответ 3

если вы хотите удалить оставшиеся "#" из 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
  }
})

Ответ 4

Это было реализовано компанией Facebook по соображениям безопасности. Здесь объяснение от Эрика Осгуда, члена команды Facebook:

Это обозначено как "по дизайну", потому что это предотвращает потенциальную уязвимость безопасности.

Некоторые браузеры добавят хэш-фрагмент из URL-адреса в конец новый URL, к которому они были перенаправлены (если этот новый URL не сам имеет хэш-фрагмент).

Например, если example1.com возвращает перенаправление на example2.com, то браузер перейдет к example1.com # abc перейдет к example2.com # abc, а хэш-фрагмент из примера1.com будет доступен для script на example2.com.

Так как существует возможность перенаправления одного потока авторизации на другой, это можно было бы получать конфиденциальные данные аутентификации из одного доступного приложения к другому.

Это смягчается добавлением нового хэш-фрагмента к URL-адресу переадресации для предотвращения этого поведения браузера.

Если эстетика или поведение на стороне клиента результирующего URL-адреса что можно было бы использовать window.location.hash(или даже перенаправление на серверной стороне), чтобы удалить символы.

Источник: https://developers.facebook.com/bugs/318390728250352/

Ответ 5

Не уверен, почему они это делают, но вы можете обойти это, перебив хэш в верхней части страницы:

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

Ответ 6

Facebook использует фрейм, и внутри него все работает с использованием AJAX-связи. Самая большая проблема в этом случае - сохранение текущего состояния страницы. Насколько я понимаю, Facebook решил использовать имитационные якоря. Это означает, что если вы щелкнули где-нибудь, они имитируют это как привязку внутри вашей страницы, и когда начинается связь AJAX, они также меняют якорный бит вашего URL-адреса.

Это решение помогает вам, когда вы пытаетесь перезагрузить страницу (не ENTER, нажмите F5), потому что ваш браузер отправляет весь URL с якорями на сервер Facebook. Поэтому Facebook поднимает последнее состояние (то, что вы видите), и затем вы можете продолжать оттуда.

Когда обратный вызов возвращается с #_=_, это означает, что страница находилась в основном состоянии до ее выхода. Поскольку этот якорь анализируется браузером, вам не нужно об этом беспокоиться.

Ответ 7

Большой раздражает, особенно для приложений, которые анализируют URI, а не просто читают $_GET... Вот взлом, который я собрал вместе... Наслаждайтесь!

<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

Вы также можете указать свой собственный хеш для параметра redirect_uri для обратного вызова Facebook, что может быть полезно при определенных обстоятельствах, например. /api/account/callback#home. Когда вы будете перенаправлены назад, это будет, по крайней мере, хеш, который соответствует известному маршруту, если вы используете backbone.js или аналогичные (не уверены в jQuery mobile).

Ответ 9

Это может стать серьезной проблемой, если вы используете JS-инфраструктуру с URL-адресами hashbang (/#!/), например. Angular. Действительно, Angular рассмотрит URL-адреса с не-hashbang-фрагментом как недопустимые и выдаст ошибку:

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

Если вы находитесь в таком случае (и перенаправляетесь на свой корень домена), вместо выполнения:

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

Просто выполните:

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

Ответ 10

Я не вижу, как эта проблема связана с facebook AJAX. На самом деле проблема также возникает с отключенными JavaScript и исключительно с переходом на основе логинов.

Пример обмена с 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#_  

Случается только с Firefox для меня тоже.

Ответ 11

Добавление на мою страницу перенаправления устраняет проблему для меня...

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

Ответ 12

С помощью angular и angular ui router вы можете исправить это

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

Ответ 13

Недавно было изменено изменение того, как Facebook обрабатывает переадресацию сеанса. См. "Изменение поведения переадресации сеанса" на этой неделе "Операция" Любовь к разработчику" в блоге для объявления.

Ответ 14

Обходной путь, который работал у меня (с использованием Backbone.js), заключался в том, чтобы добавить "#/" в конец URL-адреса переадресации, переданного в Facebook. Facebook сохранит предоставленный фрагмент и не добавит его собственный "_ = _".

По возвращении, Backbone удалит часть "#/". Для AngularJS добавление "#!" к URL-адресу возврата должен работать.

Обратите внимание, что идентификатор фрагмента исходного URL-адреса сохраняется при перенаправлении (через HTTP-коды статуса 300, 301, 302 и 303) большинством браузеров, если URL-адрес переадресации также не имеет идентификатора фрагмента. Это кажется рекомендуемым поведением.

Если вы используете обработчик script, который перенаправляет пользователя в другое место, вы можете добавить "#" к URL-адресу переадресации здесь, чтобы заменить идентификатор фрагмента пустой строкой.

Ответ 15

Для меня я перенаправляю JavaScript на другую страницу, чтобы избавиться от #_=_. Приведенные ниже идеи должны работать.:)

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

Ответ 16

Используя Angular 2 (RC5) и хэш-маршруты, я делаю это:

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

и

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

Насколько я понимаю, символ = в маршруте интерпретируется как часть определения необязательных параметров маршрута (см. https://angular.io/docs/ts/latest/guide/router.html#!#optional-route-parameters), поэтому не участвуют в сопоставлении маршрутов.

Ответ 17

Я знаю, что этот ответ задерживается, но если вы используете passjs, вы можете это увидеть.

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

Я написал это промежуточное программное обеспечение и применил его, чтобы выразить экземпляр сервера, а исходный URL-адрес у меня есть без "#_=_". Похоже, когда мы применяем экземпляр passporJS в качестве промежуточного программного обеспечения к экземпляру сервера, он не принимает эти символы, а отображается только в адресной строке наших браузеров.

Ответ 18

Я использую это, чтобы удалить символ '#'.

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