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

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


当前回答

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

This has been marked as 'by design' because it prevents a potential security vulnerability. Some browsers will append the hash fragment from a URL to the end of a new URL to which they have been redirected (if that new URL does not itself have a hash fragment). For example if example1.com returns a redirect to example2.com, then a browser going to example1.com#abc will go to example2.com#abc, and the hash fragment content from example1.com would be accessible to a script on example2.com. Since it is possible to have one auth flow redirect to another, it would be possible to have sensitive auth data from one app accessible to another. This is mitigated by appending a new hash fragment to the redirect URL to prevent this browser behavior. If the aesthetics, or client-side behavior, of the resulting URL are of concern, it would be possible to use window.location.hash (or even a server-side redirect of your own) to remove the offending characters.

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

其他回答

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

return (req, res, next) => {
    console.log(req.originalUrl);
    next();
};

我已经编写了这个中间件,并将其应用于表示服务器实例,我得到的原始URL没有“#_=_”。看起来,当我们将passporJS的实例作为中间件应用到服务器实例时,它不接受这些字符,而只在浏览器的地址栏上可见。

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

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

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

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

如果使用处理程序脚本将用户重定向到其他地方,则可以在此处的重定向URL后附加“#”,以将片段标识符替换为空字符串。

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

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

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