Facebook回调已开始将#_=_
哈希下划线附加到返回网址
有谁知道为什么?解决方案是什么?
答案 0 :(得分:231)
通过Facebook's Platform Updates:
会话重定向行为的更改
本周,我们开始在redirect_uri中添加片段#____ = ____ 此字段留空。请确保您的应用可以处理此问题 行为。
要防止这种情况,请在您的登录网址请求中设置redirect_uri,如下所示:(使用Facebook php-sdk)
$facebook->getLoginUrl(array('redirect_uri' => $_SERVER['SCRIPT_URI'],'scope' => 'user_about_me'));
<强>更新强>
以上内容正如documentation所说的那样。但是,Facebook的文档化解决方案不起作用。请考虑对Facebook Platform Updates blog post发表评论,然后按this bug获取更好的答案。在此之前,请在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>
答案 1 :(得分:104)
<强> 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
。
答案 2 :(得分:57)
如果你想从网址中删除剩余的“#”
$(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
}
})
答案 3 :(得分:35)
出于安全原因,这是由Facebook设计实现的。以下是Facebook团队成员Eric Osgood的解释:
这被标记为'按设计' 因为它可以防止潜在的安全漏洞。
某些浏览器会将URL中的哈希片段附加到a的末尾 他们被重定向到的新URL(如果新URL没有 本身有一个哈希片段。)
例如,如果example1.com返回重定向到example2.com,那么a 浏览器转到example1.com#abc将转到example2.com#abc,并且 来自example1.com的哈希片段内容可供a访问 example2.com上的脚本。
由于可以将一个身份验证流重定向到另一个身份验证流 可以从一个应用程序访问敏感的身份验证数据 到另一个。
通过将新的哈希片段附加到重定向URL来缓解这种情况 防止这种浏览器行为。
如果生成的URL的美学或客户端行为是 值得关注的是,可以使用window.location.hash(甚至是 您自己的服务器端重定向)以删除违规行为 字符。
答案 4 :(得分:10)
不确定他们为什么会这样做但是,你可以通过重置页面顶部的哈希来解决这个问题:
if (window.location.hash == "#_=_")
window.location.hash = "";
答案 5 :(得分:9)
您还可以在Facebook回调的redirect_uri
参数上指定自己的哈希值,这在某些情况下可能会有所帮助,例如: /api/account/callback#home
。当你被重定向回来时,如果你使用的是backbone.js或类似的(不确定jquery mobile),它至少会是一个与已知路由相对应的哈希值。
答案 6 :(得分:8)
Facebook使用一个框架,在其中使用AJAX通信的一切功能。这种情况下最大的问题是保留当前页面状态。据我所知,Facebook决定使用模拟锚点。这意味着如果您在某个地方单击,它们会将其模拟为页面内的锚点,并且当AJAX通信开始时,它们也会更改URL的锚点。
当您尝试重新加载页面时,此解决方案通常会帮助您(不是ENTER,请按 F5 ),因为您的浏览器会将带有锚点的整个URL发送到Facebook服务器。因此,Facebook会选择最新状态(您看到的内容),然后您就可以从那里继续。
当回调返回#_=_
时,表示该页面在离开之前处于基本状态。因为浏览器会解析此锚点,所以您无需担心它。
答案 7 :(得分: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>
答案 8 :(得分:6)
如果你使用带有hashbang(/#!/)URL的JS框架,这可能会成为一个严重的问题。角。实际上,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
答案 9 :(得分: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。
答案 10 :(得分:4)
将此添加到我的重定向页面为我解决了问题...
if (window.location.href.indexOf('#_=_') > 0) {
window.location = window.location.href.replace(/#.*/, '');
}
答案 11 :(得分:3)
使用角度和角度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 ...
});
});
答案 12 :(得分:2)
对我来说,我将JavaScript重定向到另一个页面以摆脱#_=_
。以下想法应该有效。 :)
function redirect($url){
echo "<script>window.location.href='{$url}?{$_SERVER["QUERY_STRING"]}'</script>";
}
答案 13 :(得分:2)
最近,Facebook处理会话重定向的方式发生了变化。请参阅本周{@ 3}}博客文章中的“改变会话重定向行为”。
答案 14 :(得分:2)
如果您使用的是vue-router,则可以附加到路由列表中:
{
path: '/_=_',
redirect: '/', // <-- or other default route
},
答案 15 :(得分:1)
对我有用的解决方法(使用Backbone.js)是在传递给Facebook的重定向网址末尾添加“#/”。 Facebook将保留提供的片段,而不是附加自己的“_ = _”。
返回后,Backbone将删除“#/”部分。对于AngularJS,附加“#!”返回URL应该有效。
请注意,大多数浏览器在重定向(通过HTTP状态代码300,301,302和303)时保留原始URL的片段标识符,除非重定向URL也具有片段标识符。这seems to be recommended behaviour。
如果您使用将用户重定向到其他位置的处理程序脚本,则可以在此处将“#”附加到重定向URL,以使用空字符串替换片段标识符。
答案 16 :(得分:1)
我知道这个回复很晚,但是如果你使用的是passportjs,你可能想看看这个。
return (req, res, next) => {
console.log(req.originalUrl);
next();
};
我已经编写了这个中间件并将其应用于表达服务器实例,而我得到的原始URL没有"#_=_"
。当我们将passporJS实例作为中间件应用于服务器实例时,它看起来就像它,它不接受这些字符,但只能在我们浏览器的地址栏上看到。
答案 17 :(得分:1)
我使用这个,也删除'#'符号。
<script type="text/javascript">
if (window.location.hash && window.location.hash == '#_=_') {
window.location.href = window.location.href.split('#_=_')[0];
}
</script>
答案 18 :(得分: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),因此不参与路由匹配。
答案 19 :(得分:0)
对于PHP SDK用户
我只是通过在转发之前删除多余部分来解决此问题。
$loginURL = $helper->getLoginUrl($redirectURL, $fbPermissions);
$loginURL = str_replace("#_=_", "", $loginURL);
header("Location: " . $loginURL);
答案 20 :(得分:0)
这将删除URL中附加的字符
<script type="text/javascript">
var idx=window.location.toString().indexOf("#_=_");
if (idx > 0) {
window.location = window.location.toString().substring(0, idx);
}
</script>
答案 21 :(得分:0)
最简单,最干净的解决方案,删除“#_ = _”(PHP):
代替“ header(“ Location:xxx.php”);“使用“ echo(” location.href ='xxx.php';“);”
答案 22 :(得分:0)
对于那些正在寻找简单答案的人
if (window.location.hash === "#_=_"){
history.replaceState
? history.replaceState(null, null, window.location.href.split("#")[0])
: window.location.hash = "";
}