ChatGPT解决这个技术问题 Extra ChatGPT

Facebook 回调将“#_=_”附加到返回 URL

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

有谁知道为什么?解决办法是什么?

知道facebook如何附加这些字符吗? Facebook 重定向到我的处理程序,然后我处理重定向到返回 url,但字符仍附加到 url。
@BenFoster 我想你会发现如果你使用 Fiddler 或类似的,当 FB 还原到你的处理程序时,#_=_ 就位,然后即使你对你真正想做的地方做了一个 Response.Redirect浏览器维护散列,这就是为什么只有下面建议的客户端解决方法才有效。
2017 年,怎么回事
2017年5月,还是......
2018 年 3 月……是的,还在发生

R
Ryan

通过 Facebook's Platform Updates

会话重定向行为的变化 本周,当该字段留空时,我们开始将片段#____=____ 添加到 redirect_uri。请确保您的应用可以处理此行为。

为防止这种情况,请在您的登录 url 请求中设置 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>

什么字段留空?这是非常神秘的
@Ryan Update 几乎对我有用,最后我仍然得到一个哈希 (/#)。对FB不满意。
我仍然得到 /# 以及。有人在这里更新吗?删除#
此解决方案将清除哈希: 只需确保这是 head 元素中的第一个标签。
我在此处注意到您的错误报告:developers.facebook.com/bugs/1424488987806270 我还尝试搜索“fragment request_uri”,结果相同。
P
Paul Schwarz

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 = "";

    }

}

一步步:

如果片段是#_=_,我们只会进入代码块。检查浏览器是否支持 HTML5 window.replaceState 方法。通过拆分 # 并仅获取第一部分来清理 URL。告诉历史用干净的 URL 替换当前页面状态。这会修改当前的历史条目,而不是创建一个新条目。这意味着后退和前进按钮将按照您想要的方式工作。 ;-) 如果浏览器不支持超棒的 HTML 5 历史记录方法,那么只需通过将哈希设置为空字符串来尽可能地清理 URL。这是一个糟糕的回退,因为它仍然留下一个尾随散列 (example.com/#),并且它还添加了一个历史条目,因此后退按钮将带您回到 #_-_。

详细了解 history.replaceState

详细了解 window.location


对我来说也很完美。另一种解决方案摆脱了任何查询参数。
它对谷歌omniauth做同样的事情,所以我得到一个错误没有路由匹配,它在请求uri https://.....herokua‌pp.com/auth/google_oa‌uth2/callback?state=1‌9feaacfe23423jh5jhhGS‌DFwb419049ebb18dabdf8‌&code=之后附加#(hashtag) 4/glrY3-mSlTzwe‌rwERTEG334eXcn3hOSxGu‌c51BAlglPa4AU#
比@Ryan 的解决方案更适合我,因为它不会删除查询。
该解决方案比 Ryan 的解决方案效果更好。在通过 facebook 的身份验证和 Ryan 的解决方案后,我将一些参数传递给 url,出于某种原因,只是从 url 中删除了每个参数。这个解决方案在我的情况下非常有效。
M
Mark Murphy

出于安全原因,这是由 Facebook 设计实现的。以下是 Facebook 团队成员 Eric Osgood 的解释:

这已被标记为“设计使然”,因为它可以防止潜在的安全漏洞。一些浏览器会将 URL 中的哈希片段附加到它们被重定向到的新 URL 的末尾(如果该新 URL 本身没有哈希片段)。例如,如果 example1.com 返回到 example2.com 的重定向,则转到 example1.com#abc 的浏览器将转到 example2.com#abc,并且 example2 上的脚本可以访问来自 example1.com 的哈希片段内容.com。由于可以将一个身份验证流重定向到另一个,因此可以使来自一个应用程序的敏感身份验证数据可供另一个应用程序访问。通过将新的哈希片段附加到重定向 URL 以防止这种浏览器行为,可以缓解这种情况。如果结果 URL 的美学或客户端行为受到关注,则可以使用 window.location.hash(甚至您自己的服务器端重定向)来删除有问题的字符。

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


这是真正解释为什么会发生这种情况的唯一答案,谢谢,我想我会在我的网址中留下有问题的字符,因为我知道它们不是问题。
Tumblr 在其重定向中也实现了这一点。 (截至 19 年中期)感谢您指出 FB 解释。在简单的 Passport 应用程序中轻松解决,只需将成功的重定向指向“/#”而不是“/”(这解释了为什么我在网络上看到更多尾随 octothorps,我想......)
好吧,对于使用 vue 路由器的人来说,这是一个大问题。因为它会崩溃,因为 vue 路由器期望一个有效的 js 选择器,而这不是,他们可以只设置 # 而没有其他任何东西,漏洞仍然存在减轻了,但不,他们不得不放一些更奇怪的东西,需要肮脏的变通办法
这太胖了 bs 设计它来回惹恼我。如果他们想使用 redirect_url 参数,那么允许我们为此目的传递查询参数,否则默认行为将清除它们
C
Community

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

$(window).on('load', function(e){ /*likebeats 的代码*/ } 有效。
我通过更改 e.preventDefault(); 来使用此代码;到 event.preventDefault();
此代码假设使用 jQuery,并且使用参数 e 的 onWindowReady 事件侦听器。
s
sakibmoon

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

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

p
pkiddie

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


s
sakibmoon

非常烦人,特别是对于解析 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>

在解析任何不是您创建的数据时,请小心做出假设。 URI 片段标识符早在 RFC 1738(1994 年)中就已指定,因此如果您使用正确的 URI 解析器,这绝不会成为问题。
n
neemzy

如果您使用带有 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

1.2+ ,这很棒。对于 1.0 及以下版本,请使用 window.location.hash = '';
是的,我只在 1.2 上测试过,感谢规范!
然后是html5模式
s
sakibmoon

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


s
sakibmoon

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

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

这会导致窗口位置发生变化,从而启动页面刷新
r
rebelliard

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

在这里不起作用 - 在应用 rule() 之前路由会发生变化
S
Slawomir

如果您使用的是 vue-router,则可以附加到路由列表:

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

D
Dhiren Patel

最近,Facebook 处理会话重定向的方式发生了变化。有关公告,请参阅本周 Operation Developer Love 博客文章中的“会话重定向行为的变化”。


我不确定,他在这里指的是什么
E
Eng Cy

对我来说,我将 JavaScript 重定向到另一个页面以摆脱 #_=_。下面的想法应该有效。 :)

function redirect($url){
    echo "<script>window.location.href='{$url}?{$_SERVER["QUERY_STRING"]}'</script>";        
}

我认为这不是一个好主意,因为您正在创建多个无用的请求
I
Ivo Smits

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

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

请注意,大多数浏览器在重定向(通过 HTTP 状态代码 300、301、302 和 303)时会保留原始 URL 的片段标识符,除非重定向 URL 也具有片段标识符。这个seems to be recommended behaviour

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


K
Krishna

我知道这个回复很晚,但如果你使用的是 passportjs,你可能想看看这个。

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

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


“#_=_”它仅在客户端可用。评论:en.wikipedia.org/wiki/Fragment_identifier
S
Simon

我也使用这个来删除“#”符号。

<script type="text/javascript">
    if (window.location.hash && window.location.hash == '#_=_') {
        window.location.href = window.location.href.split('#_=_')[0];
    }
</script>

N
Nanoturka

对于 PHP SDK 用户

我只是通过在转发之前删除多余的部分来解决问题。

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

R
Rotimi

这将删除附加的字符到您的网址

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

r
rcomblen

使用 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),因此不参与路由匹配。


u
user3806621

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

而不是“标题(“位置:xxx.php”);”使用 "echo ("location.href = 'xxx.php';");"


A
Akitha_MJ

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

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


这只是我的答案的副本/粘贴 stackoverflow.com/a/18305085/2694806
我只是添加这个来引用我自己,并更新了答案,链接到你的完整答案所有学分都归你@PaulSchwarz我也指的是你的答案,并且已经投票给你了