Обратный вызов Facebook начал добавлять #_=_
хэш-символ подчеркивания к URL-адресу возврата
Кто-нибудь знает, почему? Каково решение?
Обратный вызов Facebook начал добавлять #_=_
хэш-символ подчеркивания к URL-адресу возврата
Кто-нибудь знает, почему? Каково решение?
через 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>
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
- #_=_
.#
и выбрав только первую часть.history
, чтобы заменить текущее состояние страницы на чистый URL. Это изменяет текущую запись истории, а не создает новую. Это означает, что кнопки назад и вперед будут работать так, как вы хотите.; -)#_-_
.Подробнее о history.replaceState
.
Подробнее о window.location
.
если вы хотите удалить оставшиеся "#" из 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
}
})
Это было реализовано компанией 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/
Не уверен, почему они это делают, но вы можете обойти это, перебив хэш в верхней части страницы:
if (window.location.hash == "#_=_")
window.location.hash = "";
Facebook использует фрейм, и внутри него все работает с использованием AJAX-связи. Самая большая проблема в этом случае - сохранение текущего состояния страницы. Насколько я понимаю, Facebook решил использовать имитационные якоря. Это означает, что если вы щелкнули где-нибудь, они имитируют это как привязку внутри вашей страницы, и когда начинается связь AJAX, они также меняют якорный бит вашего URL-адреса.
Это решение помогает вам, когда вы пытаетесь перезагрузить страницу (не ENTER, нажмите F5), потому что ваш браузер отправляет весь URL с якорями на сервер Facebook. Поэтому Facebook поднимает последнее состояние (то, что вы видите), и затем вы можете продолжать оттуда.
Когда обратный вызов возвращается с #_=_
, это означает, что страница находилась в основном состоянии до ее выхода. Поскольку этот якорь анализируется браузером, вам не нужно об этом беспокоиться.
Большой раздражает, особенно для приложений, которые анализируют 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>
Вы также можете указать свой собственный хеш для параметра redirect_uri
для обратного вызова Facebook, что может быть полезно при определенных обстоятельствах, например. /api/account/callback#home
. Когда вы будете перенаправлены назад, это будет, по крайней мере, хеш, который соответствует известному маршруту, если вы используете backbone.js или аналогичные (не уверены в jQuery mobile).
Это может стать серьезной проблемой, если вы используете 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
Я не вижу, как эта проблема связана с 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 для меня тоже.
Добавление на мою страницу перенаправления устраняет проблему для меня...
if (window.location.href.indexOf('#_=_') > 0) {
window.location = window.location.href.replace(/#.*/, '');
}
С помощью 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 ...
});
});
Недавно было изменено изменение того, как Facebook обрабатывает переадресацию сеанса. См. "Изменение поведения переадресации сеанса" на этой неделе "Операция" Любовь к разработчику" в блоге для объявления.
Обходной путь, который работал у меня (с использованием Backbone.js), заключался в том, чтобы добавить "#/" в конец URL-адреса переадресации, переданного в Facebook. Facebook сохранит предоставленный фрагмент и не добавит его собственный "_ = _".
По возвращении, Backbone удалит часть "#/". Для AngularJS добавление "#!" к URL-адресу возврата должен работать.
Обратите внимание, что идентификатор фрагмента исходного URL-адреса сохраняется при перенаправлении (через HTTP-коды статуса 300, 301, 302 и 303) большинством браузеров, если URL-адрес переадресации также не имеет идентификатора фрагмента. Это кажется рекомендуемым поведением.
Если вы используете обработчик script, который перенаправляет пользователя в другое место, вы можете добавить "#" к URL-адресу переадресации здесь, чтобы заменить идентификатор фрагмента пустой строкой.
Для меня я перенаправляю JavaScript на другую страницу, чтобы избавиться от #_=_
. Приведенные ниже идеи должны работать.:)
function redirect($url){
echo "<script>window.location.href='{$url}?{$_SERVER["QUERY_STRING"]}'</script>";
}
Используя 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), поэтому не участвуют в сопоставлении маршрутов.
Я знаю, что этот ответ задерживается, но если вы используете passjs, вы можете это увидеть.
return (req, res, next) => {
console.log(req.originalUrl);
next();
};
Я написал это промежуточное программное обеспечение и применил его, чтобы выразить экземпляр сервера, а исходный URL-адрес у меня есть без "#_=_"
. Похоже, когда мы применяем экземпляр passporJS в качестве промежуточного программного обеспечения к экземпляру сервера, он не принимает эти символы, а отображается только в адресной строке наших браузеров.
Я использую это, чтобы удалить символ '#'.
<script type="text/javascript">
if (window.location.hash && window.location.hash == '#_=_') {
window.location.href = window.location.href.split('#_=_')[0];
}
</script>