Facebook Callback додає "# _ = _ 'до повернення URL


479

Facebook зворотний дзвінок почав додавати #_=_підкреслення хешу до Повернення URL

Хтось знає, чому? Яке рішення?


35
Будь-яка ідея, як facebook додає цих персонажів? Facebook переспрямовує до мого обробника, де я потім обробляю переспрямування до повернення URL-адреси, але символи все ще додаються до URL-адреси.
Бен Фостер

4
@BenFoster Я думаю, що ви знайдете, якщо ви використовуєте Fiddler або подібне, що коли FB перенаправляється на ваш обробник, це #_=_є на місці, то, хоча ви робите Response.Redirectтуди, де ви насправді хочете зробити, браузер підтримує хеш , саме тому це лише ті шляхи, що пропонуються на стороні клієнта, запропоновані нижче.
AakashM

17
2017, що зук
Ejonas GGgg

6
Травень 2017 року, ще ....
Мирко

5
Березень 2018..як все ще відбувається
Джон Роджерсон

Відповіді:


239

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

Зміна поведінки перенаправлення сесії

Цього тижня ми почали додавати фрагмент № ____ = ____ до redirect_uri, коли це поле не заповнено. Переконайтеся, що ваш додаток може поводитися з такою поведінкою.

Щоб цього не допустити, встановіть redirect_uri у своєму URL-адресі для входу так: (використовуючи php-sdk Facebook)

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

ОНОВЛЕННЯ

Сказане саме так, як йдеться в документації, щоб виправити це. Однак документоване рішення 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'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>

10
яке поле залишається порожнім? Це дуже
виразно

11
@Ryan Update майже працює для мене, я все одно отримую хеш (/ #) наприкінці. Не задоволений FB.
LenPopLilly

2
Я все ще отримую / #. хтось тут оновлює? щоб отримати # видалено
Tian Loon

6
Це рішення видалить хеш: <script type = "text / javascript"> var idx = window.location.toString (). IndexOf ("# _ = _"); if (idx> 0) {window.location = window.location.toString (). substring (0, idx); } </script> Просто переконайтеся, що це перший тег у головному елементі.
Горгі Ранковський

1
Я помітив тут ваш звіт про помилку: developers.facebook.com/bugs/1424488987806270 Я також спробував себе в пошуку "фрагмент запиту_урі" з тими ж результатами.
Райан

115

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. Перевірте, чи підтримує браузер window.replaceStateметод HTML5 .
    1. Очистіть URL-адресу, поділивши її #та взявши лише першу частину.
    2. Скажіть historyзамінити поточний стан сторінки чистою URL-адресою. Це змінює поточний запис історії замість створення нового. Це означає, що кнопки назад і вперед працюватимуть саме так, як вам завгодно. ;-)
  3. Якщо браузер не підтримує дивовижних методів історії HTML 5, тоді просто очистіть URL якнайкраще, встановивши хеш на порожній рядок. Це поганий запасний варіант, оскільки він все ще залишає хеш-код (example.com/#), а також додає історію, тому кнопка "назад" поверне вас до #_-_.

Дізнайтеся більше про history.replaceState.

Дізнайтеся більше про window.location.


2
Працювали чудово і для мене. Інше рішення позбавляється від будь-яких параметрів запиту.
AdeelMufti

Це те ж саме робиться і для google omniauth, тому я отримую помилку, що жоден маршрут не відповідає, додається # (хештег) після запиту uri https: //.....herokua‌ pp.com/auth/google_oa‌ uth2 / callback? state = 1‌ 9feaacfe23423jh5jhhGS‌ DFwb419049ebb18dabdf8‌ & code = 4 / glrY3-mSlTzwe‌ rwERTEG334eXcn3hOSxGu‌ c51BAlglPa4AU #
Шалафістер

Для мене працювало краще, ніж рішення @Ryan, оскільки це не видаляє запит.
olivmir

Це рішення працювало краще, ніж рішення Райана. Я передаю деякі параметри до URL після того, як він проходить через автентифікацію facebook і рішення Райана, чомусь просто видаляє кожен параметр з URL. Це рішення прекрасно працює в моєму випадку.
BlueSun3k1

59

якщо ви хочете видалити решта "#" з 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
  }
})

6
$ (window) .on ('load', function (e) {/ * code likebeats * /} працює.
ISHITOYA Kentaro

1
я використовую цей код шляхом зміни e.preventDefault (); to event.preventDefault ();
printf

Цей код передбачає jQuery, а слухач події на WindowReady бере аргумент e.
Jason Sperske

49

Це було втілено в 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/


9
Це єдина відповідь, яка насправді пояснює, чому це трапляється, дякую, я думаю, що я залишу образи в своїх адресах зараз, коли я знаю, що вони не є проблемою.
Stephenmurdoch

1
Це також реалізує Tumblr у своїх переадресаціях. (станом на середину 1919 р.) Дякую за вказівку на ФБ. Легко вирішується в спрощеному додатку Passport, просто вказуючи на успішне переспрямування на "/ #", а не просто на "/" (що пояснює, чому я бачу більше відсталих восьминоги в Інтернеті, я думаю ...)
RL Brown

10

Не впевнені, чому вони це роблять, але ви можете обійти це шляхом повторного скидання хеша вгорі сторінки:

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

9

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


8

Facebook використовує кадр, і всередині нього все функціонує за допомогою зв'язку AJAX. Найбільша проблема в цьому випадку - збереження поточного стану сторінки. Наскільки я розумію, Facebook вирішив використовувати імітовані якоря. Це означає, що якщо ви десь натиснули, вони імітують це як прив’язку до вашої сторінки, і коли AJAX зв’язок починається, вони також змінюють бік якоря вашої URL-адреси.

Це рішення допомагає вам нормально, коли ви намагаєтесь перезавантажити сторінку (не ENTER, не натискайте F5), оскільки ваш браузер надсилає всю URL-адресу з якорями на сервер Facebook. Тому Facebook бере останній стан (те, що ви бачите), і ви зможете продовжувати звідти.

Коли зворотний виклик повертається разом із #_=_цим, це означає, що сторінка була до її основного стану до виходу з неї. Оскільки цей якір розбирається браузером, вам не потрібно турбуватися про нього.


2
Якщо у вас є сценарій javascript, як backbone або ember, це питання, оскільки все після того, як хеш інтерпретується маршрутизатором
Rudi

1
Ідентифікатори фрагментів URL ("анкери") не надсилаються до браузера за запитом. Також це питання стосується OAuth, а не про головний сайт на робочому столі. Причиною цього є безпека OAuth - запобігання атакам через виправлення зловмисного URI.
AndrewF

8

Основні дратівливі, особливо для програм, які розбирають 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>

Будьте обережні, щоб робити припущення під час аналізу будь-яких даних, які ви не створюєте. Ідентифікатори фрагментів URI були специфіковані ще в RFC 1738 (у 1994 р.), Тому якщо ви використовуєте правильний аналізатор URI, це ніколи не повинно бути проблемою.
AndrewF

6

Це може стати серйозною проблемою, якщо ви використовуєте структуру JS з URL-адресами hashbang (/ #! /), Наприклад Angular. Дійсно, 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

1.2+, це працює приголомшливо. Для версії 1.0 і нижче використовуйте window.location.hash = '';
Pradeep Mahdevu

1
Так, я протестував це лише на 1,2, спасибі за специфікацію!
neemzy

А тут є режим html5
rocketspacer

5

Я не бачу, як ця проблема пов’язана з 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 і для мене.


4

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

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

1
це спричиняє зміну місця розташування вікна, ініціюючи оновлення сторінки
rpearce

3

За допомогою кутового та кутового інтерфейсу маршрутизатора ви можете це виправити

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

тут не працює - маршрут змінюється до того, як правило () буде застосовано
Maël Nison

3

Якщо ви використовуєте vue-router, ви можете додати до списку маршрутів:

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

2

Нещодавно була внесена зміна в тому, як Facebook обробляє переадресацію сесії. Дивіться "Зміни в поведінці з перенаправленням до сеансу" в цьому опублікованому блозі " Операція любові " для цього тижня .


1
Я не впевнений, що він тут має на увазі
user210504

2

Для мене я роблю переадресацію JavaScript на іншу сторінку, щоб позбутися #_=_. Нижче наведені ідеї повинні працювати. :)

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

це не гарна ідея. Я думаю, тому що ви створюєте безліч марних запитів
Jacek Pietal

1

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

Після повернення Backbone видалить частину "# /". Для AngularJS додавання "#!" до URL-адреси повернення має працювати.

Зауважте, що ідентифікатор фрагмента вихідної URL-адреси зберігається під час перенаправлення (через коди HTTP-статусу 300, 301, 302 та 303) більшістю браузерів, за винятком випадків, коли URL-адреса переадресації також має ідентифікатор фрагмента. Це , як видається, рекомендований поведінку .

Якщо ви використовуєте скрипт обробника, який перенаправляє користувача в інше місце, ви можете додати тут "#" до URL-адреси переадресації, щоб замінити ідентифікатор фрагмента порожнім рядком.


1

Я знаю, що ця відповідь запізнюється, але якщо ви використовуєте passportjs, ви можете побачити це.

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

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


3
"# _ = _" доступний лише для клієнта. Огляд: en.wikipedia.org/wiki/Fragment_identifier
альдит

1

Я використовую цей, щоб також видалити символ "#".

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

0

Використовуючи 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 ) , тому не бере участь у узгодженні маршруту.


0

Для користувачів PHP SDK

Я усунув проблему, просто видаливши зайву частину перед пересиланням.

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

0

Це видалить додані символи до вашої URL-адреси

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

0

Найпростіший і чистий рішення для видалення "# _ = _" (PHP):

Замість заголовка ("Розташування: xxx.php"); " використовувати "echo (" location.href = 'xxx.php'; ");"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.