Facebookコールバックが戻りURLに「#_ = _」を追加


479

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

なぜ誰か知っていますか?解決策は何ですか?


35
facebookがこれらのキャラクターをどのように追加するか考えていますか?Facebookはハンドラーにリダイレクトし、そこで戻りURLへのリダイレクトを処理しますが、URLには文字が追加されます。
ベンフォスター

4
私はあなたがバイオリンやFBがあなたのハンドラにredurectsときに似て使用する場合は見つけることだと思う@BenFoster、#_=_あなたがいても、その後、所定の位置にあるResponse.Redirect、あなたが実際に何をしたい場所に、ブラウザは、ハッシュを維持する理由です、機能するのは、以下で提案されているクライアント側の回避策だけです。
AakashM 2013年

17
2017年の
成功

6
2017年5月、まだ...
Mirko

回答:


239

Facebookのプラットフォームアップデート経由:

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

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

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

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

更新

上記は、ドキュメントがこれを修正するように言っているとおりです。ただし、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>

10
空白のままになっているフィールドは何ですか?これは非常に不可解です
user210504 '09 / 09/15

11
@Ryan Updateはほとんど問題なく動作しますが、最後にハッシュ(/#)を取得します。FBに不満。
LenPopLilly

2
/#も取得します。誰かここで更新しますか?#を削除するには
Tian Loon

6
このソリューションはハッシュを消去します:<script type = "text / javascript"> var idx = window.location.toString()。indexOf( "#_ = _"); if(idx> 0){window.location = window.location.toString()。substring(0、idx); } </ script>これがヘッド要素の最初のタグであることを確認してください。
Gorgi Rankovski

1
私はあなたのバグレポートに気づきました:developer.facebook.com/bugs/1424488987806270私も同じ結果で "fragment request_uri"を検索しようと試みました。
ライアンは

115

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. fragmentisの場合のみ、コードブロックに入ります#_=_
  2. ブラウザがHTML5 window.replaceStateメソッドをサポートしているかどうかを確認します。
    1. 分割し#て最初の部分のみを取得することにより、URLをクリーンアップします。
    2. 教えてhistoryきれいなURLで現在のページの状態を交換します。これにより、新しい履歴エントリが作成される代わりに、現在の履歴エントリが変更されます。これが意味することは、戻るボタンと進むボタンが思い通りに機能することです。;-)
  3. ブラウザが素晴らしいHTML 5履歴メソッドをサポートしていない場合は、ハッシュを空の文字列に設定することで、できる限りURLをクリーンアップします。後続のハッシュ(example.com/#)が残っているため、これは不適切なフォールバックであり、履歴エントリも追加されるため、[戻る]ボタンをクリックするとに戻ります#_-_

の詳細をご覧くださいhistory.replaceState

の詳細をご覧くださいwindow.location


2
私にとっても完璧に働いた。他のソリューションでは、クエリパラメータをすべて削除します。
AdeelMufti 2016年

google omniauthでも同じことを行うので、ルートが一致しないというエラーが表示されます。リクエストuri https://.....herokua‌ pp.com/auth/google_oa‌ uth2 / callback?の後に#(ハッシュタグ)が追加されますか? state = 1‌ 9feaacfe23423jh5jhhGS‌ DFwb419049ebb18dabdf8‌&code = 4 / glrY3-mSlTzwe‌ rwERTEG334eXcn3hOSxGu‌ c51BAlglPa4AU#
Shalafister's

クエリを削除しないため、@ Ryanのソリューションよりもうまく機能しました。
olivmir 2017

このソリューションは、Ryanのソリューションよりも優れていました。Facebookの認証とRyanのソリューションを通過した後、URLにいくつかのパラメーターを渡します。何らかの理由で、URLからすべてのパラメーターを削除します。このソリューションは私の場合完全に機能します。
BlueSun3k1 2017年

59

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

6
$(ウィンドウ).on( 'ロード'、機能(E){/ * likebeatsのコード* /}作品。
ISHITOYA健太郎

1
私はe.preventDefault();を変更してこのコードを使用します。to event.preventDefault();
printf 2013

このコードは、jQuery、および引数を取るonWindowReadyイベントリスナーを想定していますe
Jason Sperske、2015

49

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

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

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

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

ある認証フローを別の認証フローにリダイレクトすることが可能であるため、あるアプリから別のアプリにアクセスできる機密認証データを持つことが可能です。

これは、新しいURLフラグメントをリダイレクトURLに追加して、このブラウザーの動作を防ぐことにより軽減されます。

結果のURLの美観、つまりクライアント側の動作が問題になる場合は、window.location.hash(または独自のサーバー側リダイレクト)を使用して問題のある文字を削除することができます。

出典:https : //developers.facebook.com/bugs/318390728250352/


9
これが発生する理由を実際に説明する唯一の回答です。おかげで、問題のない文字が問題でないことがわかったので、URLに問題の文字を残しておきます。
スティーブンマードック2017年

1
これは、リダイレクトでTumblrによっても実装されます。('19年半ば現在)FBの説明を指摘してくれてありがとう 成功したリダイレクトを単に "/"ではなく "/#"にポイントするだけで、単純化したPassportアプリで簡単に解決できます(これにより、Webに後続のoctororpsが表示される理由がわかります...)
RL Brown

10

彼らがこれをしている理由はわかりませんが、ページの上部にあるハッシュをリセットすることで回避できます。

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

9

redirect_uriFacebookコールバックのパラメータに独自のハッシュを指定することもできます。これは、特定の状況で役立つ場合があります/api/account/callback#home。リダイレクトされると、backbone.jsなどを使用している場合、既知のルートに対応するハッシュになります(jquery mobileについては不明)。


8

Facebookはフレームを使用し、その内部ではすべてAJAX通信を使用して機能します。この場合の最大の問題は、現在のページの状態を保持することです。私が理解している限り、Facebookはシミュレートされたアンカーを使用することにしました。つまり、どこかをクリックすると、ページ内のアンカーとしてシミュレーションされ、AJAX通信が開始されると、URLのアンカービットも変更されます。

このソリューションはF5、ブラウザがアンカー付きのURL全体をFacebookサーバーに送信するため、ページをリロードしようとするとき(ENTERではなく、を押す)に通常役立ちます。したがって、Facebookは最新の状態(表示)を取得し、そこから続行できます。

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


2
バックボーンやエンバーなどのJavaScriptフレームワークを使用している場合、ハッシュがルーターによって解釈された後のすべてが問題となる
Rudi

1
URLフラグメント識別子(「アンカー」)は、要求時にブラウザー送信されません。また、この質問はOAuthに関するものであり、メインのデスクトップサイトに関するものではありません。この理由は、OAuthセキュリティ -悪意のあるリダイレクトURIの作成による攻撃の防止です。
AndrewF 2013年

8

特に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パーサーを使用すれば、これは問題になりません。
AndrewF 2013年

6

これは、Angularなどのハッシュバング(/#!/)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

1.2+、これは素晴らしい働きをします。1.0以下ではwindow.location.hash = '';を使用します。
Pradeep Mahdevu 2013

1
はい、仕様のおかげで、私はこれを1.2でのみテストしました!
13

そして、html5モードがあります
ロケットスペーサー2017

5

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


4

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

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

1
これにより、ウィンドウの場所が変更され、ページの更新が開始されます
rpearce

3

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

ここでは動作しません-ルールの前にルート変更を()に適用される
MAEL二尊院

3

vue-routerを使用している場合は、ルートのリストに追加できます。

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


2

私は、JavaScriptを別のページにリダイレクトして、を取り除き#_=_ます。以下のアイデアはうまくいくはずです。:)

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

あなたが複数の無駄なリクエストを作成しているので、これは良い考えではないと思います
Jacek Pietal

1

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

戻ると、Backboneは「#/」の部分を削除します。AngularJSの場合、「#!」を追加します 戻りURLが機能するはずです。

リダイレクトURLにもフラグメント識別子がない場合を除き、元のURLのフラグメント識別子は、ほとんどのブラウザーによるリダイレクト(HTTPステータスコード300、301、302、303を介して)で保持されることに注意してください。これは推奨される動作のようですです。

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


1

私はこの返信が遅いことを知っていますが、passportjsを使用している場合は、これを確認することをお勧めします。

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

このミドルウェアを作成してExpressサーバーインスタンスに適用したところ、取得した元のURLにはがありません"#_=_"。passporJSのインスタンスをミドルウェアとしてサーバーインスタンスに適用すると、これらの文字は使用されませんが、ブラウザのアドレスバーにのみ表示されます。


3
"#_ = _"クライアントでのみ使用できます。レビュー:en.wikipedia.org/wiki/Fragment_identifier
alditis '28

1

これを使用して、「#」記号も削除します。

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

0

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

PHP SDKユーザーの場合

転送する前に余分な部分を取り除くだけで問題を解決しました。

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

0

これにより、URLに追加された文字が削除されます

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

0

"#_ = _"を削除する最も簡単でクリーンなソリューション(PHP):

「header( "Location:xxx.php");」の代わりに 「echo( "location.href = 'xxx.php';");」を使用するには

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.