此解决方案将删除散列:
不知道他们为什么要这样做,但是,您可以通过在页面顶部重新设置哈希来绕过这个问题:
1 2
| if (window.location.hash =="#_=_")
window.location.hash =""; |
您还可以在facebook回调的redirect_uri参数上指定自己的散列值,这在某些情况下可能会有所帮助,例如/api/account/callback#home。当您被重新定向回来时,如果您使用的是backbone.js或类似工具(不确定jquery mobile),那么它至少是一个对应于已知路由的哈希。
Facebook使用一个框架,框架内部的所有功能都使用Ajax通信。这种情况下最大的问题是保存当前页面状态。据我所知,Facebook决定使用模拟锚。这意味着,如果您单击了某个地方,它们会将其模拟为页面内的锚,当Ajax通信开始时,它们也会更改URL的锚位。
此解决方案在您尝试重新加载页面时(不输入,请按f5)通常会帮助您,因为您的浏览器会将带有锚定的整个URL发送到Facebook服务器。因此,Facebook会获取最新的状态(你所看到的),然后你就可以从那里继续了。
当回调使用#_=_返回时,意味着页面在离开之前处于基本状态。因为这个锚是由浏览器解析的,所以您不必担心它。
- 如果您有一个像主干或ember这样的javascript框架,那么在路由器解释散列之后,它就成了一个问题。
- URL片段标识符("锚")不会根据请求发送到浏览器。另外,这个问题是关于OAuth的,而不是关于主桌面站点的。这样做的原因是OAuth安全性——防止由于伪造恶意重定向URI而导致的攻击。
主要的恼人之处,尤其是对于解析URI而不仅仅是读取$的应用程序…这是我放在一起的黑客…享受!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <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);
}
</head>
<body>
URI should be clean
</body>
</html> |
- 在分析任何您没有创建的数据时,请注意假设。早在RFC1738(1994年)就已经对URI片段标识符进行了规范化,所以如果您使用了正确的URI解析器,这就永远不会是问题。
如果将JS框架与hashbang一起使用,这可能会成为一个严重的问题。/)URL,例如角。事实上,Angular会将带有非hashbang片段的URL视为无效,并抛出一个错误:
1
| Error: Invalid url"http://example.com/#_=_", missing hash prefix"#!". |
如果您遇到这种情况(并重定向到您的域根目录),而不是这样做:
1
| window.location.hash = ''; // goes to /#, which is no better |
简单地做:
1
| window.location.hash = '!'; // goes to /#!, which allows Angular to take care of the rest |
- 1.2+,这太棒了。对于1.0及以下版本,请使用window.location.hash='';
- 是的,我只在1.2上测试了这个,谢谢您的规范!
- 然后是HTML5模式
我不知道这个问题与Facebook Ajax有什么关系。事实上,禁用javascript和纯基于重定向的登录也会出现此问题。
与Facebook的交流示例:
1 2 3
| 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#_ |
只有在我使用火狐时才会发生。
将此添加到我的重定向页修复了问题…
1 2 3
| if (window.location.href.indexOf('#_=_') > 0) {
window.location = window.location.href.replace(/#.*/, '');
} |
有了角度和角度的用户界面路由器,你可以解决这个问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| 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 ...
});
}); |
如果您使用的是Vue路由器,则可以附加到路由列表:
1 2 3 4
| {
path: '/_=_',
redirect: '/', // <-- or other default route
}, |
对于我来说,我将javascript重定向到另一个页面,以摆脱#_=_。下面的想法应该有效。:)
1 2 3
| function redirect($url){
echo"window.location.href='{$url}?{$_SERVER["QUERY_STRING"]}'";
} |
- 我认为这不是一个好主意,因为您正在创建多个无用的请求
最近Facebook在如何处理会话重定向方面引入了一个变化。请参阅本周的OperationDeveloperLove博客文章中的"会话重定向行为的改变"以了解该公告。
对于我(使用主干网.js)来说,一个有效的解决方法是在传递到Facebook的重定向URL的末尾添加"/"。Facebook将保留所提供的片段,而不附加自己的"uuuu"。
返回后,主干将移除"/"部分。对于AngularJS,附加"!"返回的URL应该有效。
请注意,大多数浏览器在重定向时(通过HTTP状态代码300、301、302和303)保留原始URL的片段标识符,除非重定向URL也具有片段标识符。这似乎是推荐的行为。
如果使用将用户重定向到其他位置的处理程序脚本,则可以在此处将""附加到重定向URL,以用空字符串替换片段标识符。
我知道这个回复很晚了,但是如果你使用的是PassportJS,你可能会想看看这个。
1 2 3 4
| return (req, res, next) => {
console.log(req.originalUrl);
next();
}; |
我已经编写了这个中间件并将其应用于Express服务器实例,我得到的原始URL没有"#_=_"。看起来,当我们将passorjs实例作为中间件应用到服务器实例时,它不使用这些字符,而是只在浏览器的地址栏上可见。
- "u=uu"它只在客户机上可用。评论:en.wikipedia.org/wiki/fragment_identifier
我用这个来删除符号。
1 2 3 4
| <script type="text/javascript">
if (window.location.hash && window.location.hash == '#_=_') {
window.location.href = window.location.href.split('#_=_')[0];
} |
使用角度2(rc5)和基于散列的路由,我这样做:
1 2 3 4 5
| const appRoutes: Routes = [
...
{path: '_', redirectTo: '/facebookLoginSuccess'},
...
] |
和
1
| export const routing = RouterModule.forRoot(appRoutes, { useHash: true }); |
据我所知,路由中的=字符被解释为可选路由参数定义的一部分(参见https://angular.io/docs/ts/latest/guide/router.html!#可选的路由参数),因此不涉及路由匹配。
对于php-sdk用户
我解决了这个问题,只是在转发前去掉了多余的部分。
1 2 3
| $loginURL = $helper->getLoginUrl($redirectURL, $fbPermissions);
$loginURL = str_replace("#_=_","", $loginURL);
header("Location:" . $loginURL); |
这将删除URL中附加的字符
1 2 3 4 5
| <script type="text/javascript">
var idx=window.location.toString().indexOf("#_=_");
if (idx > 0) {
window.location = window.location.toString().substring(0, idx);
} |