it-swarm.com.ru

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

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

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

442
zing ming

через Обновления платформы Facebook :

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

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

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

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

ОБНОВЛЕНИЕ

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

<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'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 = "";
}

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

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

    }

}

Шаг за шагом:

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

Узнайте больше о history.replaceState .

Узнайте больше о window.location .

99
PapaSierra

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

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

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

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

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

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

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

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

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

33
Mark Murphy

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

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

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

9
pkiddie

Главное раздражает, особенно для приложений, которые анализируют 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
Jeremy Whitt

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

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

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

8
Sándor Tóth

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

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
6
neemzy

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

Пример обмена с фейсбуком: 

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 для меня тоже.

5
Sebastian Tusk

Добавление этого к моей странице перенаправления решило проблему для меня ...

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

С помощью углового и углового UI-маршрутизатора вы можете это исправить 

    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

Если вы используете vue-router, вы можете добавить в список маршрутов:

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

Недавно было внесено изменение в то, как Facebook обрабатывает перенаправления сеансов. См. "Изменение в поведении перенаправления сеанса" в этом сообщении Operation Developer Love в блоге.

2
Dhiren Patel

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

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

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

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

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

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

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

1
Krishna

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

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

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

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

1
Ivo Smits

Для PHP пользователей SDK

Я исправил проблему, просто удалив лишнюю часть перед пересылкой.

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

Используя 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 -параметры ), поэтому не участвуют в сопоставлении маршрута.

0
rcomblen

Это приведет к удалению добавленных символов в ваш 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