Facebook回调追加'#_=_'返回URL

Facebook回调已经开始将#_=_哈希下划线添加到返回URL

有人知道为什么吗?解决方案是什么?

127783 次浏览

不知道他们为什么这样做,但是,你可以通过重置页面顶部的哈希来解决这个问题:

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

我看不出这个问题与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#_

我也只在火狐浏览器上遇到过这种情况。

Facebook最近在处理会话重定向的方式上做出了改变。请参阅本周运营开发者之爱博客文章中的“会话重定向行为的变化”以了解公告。

通过Facebook的平台更新:

更改会话重定向行为

本周,我们开始在redirect_uri中添加一个片段#____=____ 该字段为空。请确保您的应用程序可以处理这个问题 行为。< / p >

为了防止这种情况,在你的登录url请求中设置redirect_uri(使用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>

主要恼人的,特别是应用程序解析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>

如果您想从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
}
})

将此添加到我的重定向页面解决了我的问题…

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

你也可以在Facebook回调的redirect_uri参数上指定你自己的哈希,这在某些情况下可能是有帮助的,例如/api/account/callback#home。当你被重定向回来,它至少是一个哈希,对应于一个已知的路由,如果你使用backbone.js或类似的(不确定jquery移动)。

博士TL;

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. 李< / ol > < / >
    4. 如果浏览器不支持了不起的HTML 5历史方法,那么只需通过将散列设置为空字符串来尽可能地清理URL。这是一个糟糕的后退,因为它仍然留下一个尾随散列(example.com/#)并且它还添加了一个历史记录条目,所以返回按钮将带你回到#_-_

    了解关于history.replaceState的更多信息。

    了解关于window.location的更多信息。

如果你使用的是带有hashbang (/#!/) url的JS框架,比如Angular,这可能会成为一个严重的问题。实际上,Angular会认为带有非hashbang片段的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

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

一个对我有用的解决方法(使用Backbone.js)是在传递给Facebook的重定向URL的末尾添加“#/”。Facebook将保留提供的片段,而不会附加自己的“_=_”。

返回时,Backbone将删除“#/”部分。对于AngularJS,在返回URL后附加“#!”应该可以工作。

注意,大多数浏览器在重定向(通过HTTP状态码300、301、302和303)时保留原始URL的片段标识符,除非重定向URL也有片段标识符。这似乎是被推荐的行为

如果使用处理程序脚本将用户重定向到其他地方,则可以在此处的重定向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),因此不涉及路由匹配。

这是Facebook出于安全考虑而设计的。下面是Facebook团队成员埃里克·奥斯古德的解释:

这已被标记为“设计” 因为它防止了一个潜在的安全漏洞 一些浏览器会将URL的散列片段附加到URL的末尾 他们被重定向到的新URL(如果新URL没有

例如,如果example1.com返回一个重定向到example2.com,则a 浏览器转到example1.com#abc将转到example2.com#abc,而 可以访问example1.com中的散列片段内容

由于有可能有一个认证流重定向到另一个,它 是否有可能从一个应用程序访问敏感的身份验证数据 到另一个地方。< / p > 通过向重定向URL附加一个新的散列片段来缓解这一问题

.

.

如果结果URL的美学或客户端行为为 值得注意的是,可以使用window.location.hash(甚至 您自己的服务器端重定向)以删除有问题的内容 字符。< / p >

来源:https://developers.facebook.com/bugs/318390728250352/

我知道这个回复晚了,但如果您正在使用passportjs,您可能想看到这个。

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>

适用于PHP SDK用户

我只是通过在转发之前删除额外的部分来解决这个问题。

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

这将删除附加字符到您的url

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

如果你使用vue-router,你可以添加到路由列表:

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

最简单和干净的解决方案删除#_=_&;(PHP):

用“echo(”Location .php)代替“header("Location: xxx.php");"Href = 'xxx.php';");"

对于那些正在寻找简单答案的人 只要加上这个,它对我有用

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

请查看Paul Schwarz的完整回答

https://stackoverflow.com/a/18305085/2694806 < a href = " https://stackoverflow.com/a/18305085/2694806 " > < / >