Facebookcallback追加'#_ = _'返回URL
Facebookcallback已经开始将#_=_
hash下划线附加到返回URL
有谁知道为什么? 解决办法是什么?
通过Facebook的平台更新 :
会话redirect行为的变化
本周,当这个字段留空时,我们开始向redirect_uri添加一个片段#____ = ____。 请确保您的应用可以处理这种行为。
为了防止这种情况,请在您的loginurl请求中设置redirect_uri,如下所示:(使用Facebook的php-sdk)
$facebook->getLoginUrl(array('redirect_uri' => $_SERVER['SCRIPT_URI'],'scope' => 'user_about_me'));
UPDATE
以上是正如文件说,以解决这个问题。 但是,Facebooklogging的解决scheme不起作用。 请考虑在Facebook平台更新博客文章留言,并按照此错误获得更好的答案。 在此之前,将以下内容添加到您的head标签来解决此问题:
<script type="text/javascript"> if (window.location.hash && window.location.hash == '#_=_') { window.location.hash = ''; } </script>
或者更详细的select(谢谢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>
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
是#_=_
我们将只进入代码块。 - 检查浏览器是否支持HTML5 window.replaceState方法。
- 通过在
#
分开并只取第一部分来清理URL。 - 告诉
history
用干净的URLreplace当前的页面状态。 这会修改当前的历史logging,而不是创build一个新的历史logging。 这意味着后退和前进button将以您想要的方式工作。 😉
- 通过在
- 如果浏览器不支持令人敬畏的HTML 5历史logging方法,那么只要将散列设置为空string,就可以最好地清理URL。 这是一个糟糕的后备,因为它仍然留下一个尾随散列(example.com/#),并且它还添加了一个历史logging条目,所以后退button将带你回到
#_-_
。
了解关于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 } })
出于安全原因,这由Facebookdevise实施。 以下是来自Facebook团队成员Eric Osgood的解释:
这已被标记为“按devise”,因为它可以防止潜在的安全漏洞。
某些浏览器会将散列片段从URL追加到新的URL(如果新URL本身没有散列片段)的末尾。
例如,如果example1.com返回一个redirect到example2.com,那么去example1.com#abc的浏览器将转到example2.com#abc,并且来自example1.com的哈希片段内容可以被example2上的脚本访问.COM。
由于可以将一个authenticationstream程redirect到另一个authenticationstream程,因此可以从另一个应用程序访问一个应用程序的敏感authentication数据。
这可以通过在redirectURL中附加一个新的哈希碎片来缓解这种浏览器行为。
如果所得到的URL的美学或客户端行为值得关注,那么可以使用window.location.hash(甚至是您自己的服务器端redirect)来删除违规字符。
资料来源: https : //developers.facebook.com/bugs/318390728250352/
不知道他们为什么这样做,但是,您可以通过重置页面顶部的散列来解决这个问题:
if (window.location.hash == "#_=_") window.location.hash = "";
Facebook使用框架,并使用AJAX通讯function。 在这种情况下最大的问题是保留当前的页面状态。 据我所知,Facebook决定使用模拟锚。 这意味着如果你点击某个地方,他们将模拟它作为页面内的锚点,当AJAX通信开始时,它们也会更改URL的锚点。
这个解决scheme通常可以帮助您在尝试重新加载页面时(不是input,按F5 ),因为您的浏览器将带锚的整个URL发送到Facebook服务器。 因此,Facebook拿起最新的状态(你看到的),然后你可以继续从那里。
当callback以#_=_
返回时,表示页面在离开之前处于基本状态。 由于这个锚点是由浏览器parsing的,所以你不用担心。
主要恼人的,特别是对parsingURI的应用程序,而不是只读$ _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>
您也可以在Facebookcallback的redirect_uri
参数上指定您自己的散列,这在某些情况下可能会有所帮助,例如/api/account/callback#home
。 当你被redirect回来的时候,如果你使用的是backbone.js或类似的(不知道jquery mobile),它至less会是一个对应于已知路由的哈希。
如果你正在使用带有hashbang(/#!/)URL的JS框架,比如Angular,这可能会变成一个严重的问题。 事实上,Angular会将带有非hashbang片段的URL视为无效,并抛出一个错误:
Error: Invalid url "http://example.com/#_=_", missing hash prefix "#!".
如果您处于这种情况(并redirect到您的域根目录),而不是:
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禁用和基于redirect的login也会出现问题。
与facebook交stream的示例:
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上。
添加到我的redirect页面解决了我的问题…
if (window.location.href.indexOf('#_=_') > 0) { window.location = window.location.href.replace(/#.*/, ''); }
与angular和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 ... }); });
最近在Facebook如何处理会话redirect时引入了一个变化。 请参阅本周的Operation Developer Love博客中的“更改会话redirect行为”。
我使用的解决方法(使用Backbone.js)是在传递给Facebook的redirectURL的末尾添加“#/”。 Facebook将保留提供的片段,而不是附加它自己的“_ = _”。
返回后,Backbone将删除“#/”部分。 对于AngularJS,追加“#!” 到返回的URL应该工作。
请注意,原始URL的片段标识符在大多数浏览器的redirect(通过HTTP状态代码300,301,302和303)时被保留,除非redirectURL也具有片段标识符。 这似乎是推荐的行为 。
如果您使用将用户redirect到其他位置的处理程序脚本,则可以在这里将“#”附加到redirectURL,以便用空stringreplace片段标识符。
对我来说,我把JavaScriptredirect到另一个页面来摆脱#_=_
。 下面的想法应该工作。 🙂
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 });
据我所知,path中的=
字符被解释为可选路由参数定义的一部分(请参阅https://angular.io/docs/ts/latest/guide/router.html#ts#optional-route-parameters ),所以不参与路线匹配。
我知道这个回复迟了,但是如果你使用passportjs,你可能想看到这个。
return (req, res, next) => { console.log(req.originalUrl); next(); };
我已经写了这个中间件,并用它来表示服务器实例,而我得到的原始URL没有"#_=_"
。 看起来,当我们将passporJS的实例作为中间件应用到服务器实例时,它并不需要这些字符,而只能在浏览器的地址栏上看到。
- iPhone开发:创build滑动抽屉如path和Facebook应用程序
- 为什么当我甚至不使用Bolts的时候,我得到了有关Bolts框架和FacebookSDK的错误?
- C# – HttpWebRequest POST(login到Facebook)
- iOSparsingFacebooklogin错误308 FBSDKLoginBadChallengeString
- 在本地主机上运行Facebook应用程序
- 未捕获的OAuthException:必须使用活动的访问令牌来查询有关当前用户的信息
- Facebook Javascript SDK问题:“FB没有定义”
- Facebook SDK:应用程序未注册为URLscheme
- 如何在search = xxxsearchFacebook Graph API时获得Like Count数量