web-dev-qa-db-ja.com

Facebookのコールバックは、URLを返すために '#_ = _'を追加します

FacebookのコールバックがReturn URLに#_=_ハッシュアンダースコアを追加し始めました

誰もがその理由を知っていますか?解決策は何ですか?

453
zing ming

via Facebookのプラットフォームアップデート

セッションリダイレクト動作の変更

今週は、このフィールドを空白のままにして、redirect_uriに#____ = ____というフラグメントを追加し始めました。アプリがこの動作を処理できることを確認してください。

これを防ぐには、ログインURLリクエストでredirect_uriを次のように設定します。(Facebook php-sdkを使用)

$facebook->getLoginUrl(array('redirect_uri' => $_SERVER['SCRIPT_URI'],'scope' => 'user_about_me'));

UPDATE

上記は、これを修正するための ドキュメント とまったく同じです。ただし、Facebookの文書化された解決策は機能しません。より良い答えを得るために Facebook Platform Updatesブログ投稿 にコメントを残して このバグ に従ってください。それまでは、この問題を解決するために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>
231
Ryan

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

    }

}

ステップバイステップ:

  1. fragment#_=_の場合にのみコードブロックに入ります。
  2. ブラウザがHTML5のwindow.replaceStateメソッドをサポートしているか確認してください。
    1. #を分割して最初の部分だけを取って、URLをきれいにします。
    2. 現在のページの状態をクリーンなURLに置き換えるようにhistoryに指示します。これは新しいものを作成する代わりに現在の履歴エントリを修正します。これが意味するのは、戻るボタンと進むボタンがちょうどあなたが望むように機能するということです。 ;-)
  3. ブラウザが素晴らしいHTML 5の履歴メソッドをサポートしていない場合は、ハッシュを空の文字列に設定することで可能な限りURLをクリーンアップしてください。末尾のハッシュ(example.com/#)が残っていて履歴エントリが追加されるため、これは不適切な代替方法です。[戻る]ボタンをクリックすると#_-_に戻ります。

history.replaceState についてさらに学んでください。

window.location についてさらに学んでください。

105
PapaSierra

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
  }
})
58
likebeats

これは、セキュリティ上の理由から、意図的にFacebookによって実装されました。 FacebookチームのメンバーであるEric Osgoodによる説明は次のとおりです。

これは潜在的なセキュリティ上の脆弱性を防ぐため、「設計上」とマークされています。

ブラウザによっては、リダイレクト先の新しいURLの末尾にURLからハッシュフラグメントを追加します(その新しいURL自体にハッシュフラグメントがない場合)。

たとえば、example1.comがexample2.comへのリダイレクトを返した場合、example1.com#abcにアクセスするブラウザはexample2.com#abcに移動し、example1.comのハッシュフラグメントコンテンツはexample2のスクリプトにアクセス可能になります。 .com.

ある認証フローを別の認証フローにリダイレクトさせることは可能であるため、あるアプリケーションの機密認証データを別のアプリケーションからアクセス可能にすることは可能です。

このブラウザの動作を防ぐために、リダイレクトURLに新しいハッシュフラグメントを追加することでこれを軽減します。

結果として得られるURLの美しさ、つまりクライアントサイドの振る舞いが問題になる場合は、window.location.hash(またはサーバーサイドのリダイレクト)を使って問題のある文字を削除することが可能です。

ソース: https://developers.facebook.com/bugs/318390728250352/

35
Mark Murphy

なぜ彼らがこれをしているのかわからないが、あなたはあなたのページのトップでハッシュをリセットすることによってこれを回避することができる:

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

Facebookコールバックのredirect_uriパラメータにあなた自身のハッシュを指定することもできます。 /api/account/callback#home。リダイレクトされると、backbone.jsなどを使用している場合は、少なくとも既知のルートに対応するハッシュになります(jquery mobileについてはよくわかりません)。

9
pkiddie

特に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
Jeremy Whitt

Facebookはフレームを使用し、その内部はすべてAJAX通信を使用して機能します。この場合の最大の問題は、現在のページ状態を維持することです。私が理解している限りでは、Facebookは擬似アンカーを使用することを決めました。つまり、あなたがどこかをクリックした場合、それはあなたのページの内側のアンカーとしてそれをシミュレートし、そしてAJAXコミュニケーションが始まるとき、彼らは同様にあなたのURLのアンカービットを変更します。

あなたがページをリロードしようとするとき、この解決策は通常あなたを助けます F5ブラウザがアンカー付きのURL全体をFacebookサーバーに送信するからです。したがって、Facebookは最新の状態(あなたが見ているもの)を選び出し、そこから先へ進むことができます。

コールバックが#_=_で戻るとき、それはそのページがそれを出る前の基本状態にあったことを意味します。このアンカーはブラウザによって解析されるので、心配する必要はありません。

8
Sándor Tóth

ハッシュバング(/#!/)URLを持つJSフレームワークを使用している場合、これは一種の深刻な問題になる可能性があります。角度があります。実際、Angularは、ハッシュバング以外のフラグメントを含む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
6
neemzy

この問題が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だけで起こります。

5
Sebastian Tusk

私のリダイレクトページにこれを追加することは私のための問題を解決しました...

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

角度と角度の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 ...
    });
});
3
rebelliard

あなたがvue-routerを使っているなら、あなたはルートのリストに追加することができます:

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

Facebookがセッションのリダイレクトを処理する方法に変更が最近導入されました。この発表については、今週の Operation Developer Love ブログ投稿の「セッションリダイレクト動作の変更」を参照してください。

2
Dhiren Patel

私にとっては、私は#_=_を取り除くためにJavaScriptを別のページにリダイレクトさせます。以下の考えはうまくいくはずです。 :)

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

私はこれを使って '#'記号も削除します。

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

私はこの返事が遅れているのを知っています、しかしあなたがpassportjsを使っているならば、あなたはこれを見たいと思うかもしれません。

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

私はこのミドルウェアを書き、エクスプレスサーバーインスタンスにそれを適用しました、そして私が手に入れたオリジナルのURLは"#_=_"なしです。サーバーインスタンスにミドルウェアとしてpassporJSのインスタンスを適用すると、そのように見えますが、それらの文字は使用されませんが、ブラウザのアドレスバーにのみ表示されます。

1
Krishna

(Backbone.jsを使用して)私にとってうまくいった回避策は、Facebookに渡されたリダイレクトURLの最後に "#/"を追加することでした。 Facebookは提供されたフラグメントを保持し、独自の "_ = _"を追加しません。

戻ると、Backboneは "#/"部分を削除します。 AngularJSの場合は、「#!」を追加します。リターンURLにはうまくいくはずです。

元のURLのフラグメントIDは、リダイレクトURLにフラグメントIDも含まれていない限り、ほとんどのブラウザでリダイレクト時に(HTTPステータスコード300、301、302、および303を介して)保持されます。これ 推奨される動作のようです

ユーザを別の場所にリダイレクトするハンドラスクリプトを使用する場合は、ここでリダイレクトURLに「#」を追加して、フラグメント識別子を空の文字列に置き換えることができます。

1
Ivo Smits

PHP SDKユーザーの場合

転送する前に余分な部分を削除することで問題を解決しました。

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

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 )、ルートマッチングには関与しません。

0
rcomblen

これはあなたのURLに追加された文字を削除します

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