3

「Race Condition」とは何かと疑問に思っている場合は、システムの欠陥ですが、タイミングに大きく依存しています。詳細については、こちらのウィキを参照してください。

したがって、私が持っている条件は、Facebook Connect に関連し、ASP.NET 4.0 Web アプリケーション (フォーム ベース認証 - IIS7) を使用してシングル サインオン サービスを実装することです。

プロセス自体(ログアウトを含む)はうまく機能していますが、.....

100% 正確に機能していないシナリオを次に示します。

  1. ユーザーが Facebook にログインします。
  2. ユーザーが私のウェブサイトに移動します。
  3. ユーザーは自動的にログインされません (ただし、ログインする必要があります)。
  4. ユーザーがページを更新すると、自動的にログインされます。

ステップ 3 でコードをブレークポイントすると、Facebook の Cookie はまだ存在しません ( HttpContext.Current.Request.Cookies.

しかし、ページがリロードされると (ステップ 4)、Facebook の Cookie が存在します。

私にとって、それはいくつかの可能性があります:

Facebook が私のアプリケーションに Cookie へのアクセスを許可していないだけなのか (クロスドメイン ハンドシェイクの遅延 - xd_receiver.htm)、クロスドメイン Cookie 自体と ASP の問題なのかはわかりませ。 NET ページのライフサイクル。

他の誰かがこの問題に対処しましたか?

これは「万能」ではありませんが、面倒です (そして、ユーザーの観点からはあまり良くありません)。

編集:

わかりました、今何か変なことに気づきました。(Facebook経由で)Facebookにログインし、20秒待ってから私のWebサイトにアクセスすると、まだログインしません。2回目のロード後にのみログインします。タイミングの問題ではないかもしれません-なぜですかCookie を読み取るには 2 回更新する必要がありますか?

混乱を解消するために、Facebook は Cookie を設定し (ユーザーが Facebook にログインしている)、私の Web サイトはこれらの Cookie を読み取ります。

これは、すべてのページ要求で発生します (すべての単一ページにあるユーザー コントロールのロジック)。

protected void Page_PreRender(object sender, EventArgs eventArgs)
{
   if (FacebookUser.IsAuthenticated) // static property, checks HttpContext.Request.Cookies
   {
        // log them into my website
   }
}

したがって、最初の更新では、HttpContext.Request.Cookies には何もありません。

2 回目の更新では、それらはそこにあります。

これは、ページ要求ごとに FB.Init がクライアント側で実行されるためだと思います。これは、Cookie を初期化するものです。そのため、(Facebook にログインした後) サーバー側 (Cookie をチェックする場所) で初めて私の Web サイトにアクセスしたとき、この関数はまだ実行されていません。

だから私はここで負け戦を戦っていると思います(クライアント側に設定されているCookieサーバー側にアクセスしようとしています)。

編集2:

これが私の初期化コードです(window.loadで実行):

FB.init('myapikey', 'xd_receiver.htm', null);

私は今、次のようなことをしようとしています:

FB.init('myapikey', 'xd_receiver.htm', null);
FB.getLoginStatus(function(response) {
  if (!response.session) {
      return false;
  }
  else {
    window.location.reload();
  }
});

しかし、JavaScript エラーが発生しています。「FB.getLoginStatus」は関数ではありません。=(

これは、次の JavaScript ライブラリを使用しているためです: http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US

他の人はこれを使うと言っていますが: http://connect.facebook.net/en_US/all.js

新しい JS API の doco を見ていました。

このスレッドに出くわした他の人への参照として、ここに「古い」JS API のドコがあります: http://developers.facebook.com/docs/reference/oldjavascript/

したがって、FB.Connect.get_status() を使用してこの問題を解決し、ユーザーが認証されている場合はウィンドウをリロードします。

みんなの助けに感謝します。

これは、他の誰かが気にする場合の問題に対する私の「解決策」です。

window.onload = function() { 
                FB.init('{0}', 'xd_receiver.htm');
                FB.ensureInit(function() {
                   FB.Connect.ifUserConnected(onUserConnected, onUserNotConnected); 
                });
            };

            function onUserConnected() {
                alert('connected!');
                window.location.reload();
            }

            function onUserNotConnected() {
                alert('not connected');
            }

もちろん、window.location.reload() を実行する前に、フォーム認証 Cookie を確認する必要があります。そうしないと、ページが更新され続けます。=)

4

4 に答える 4

1

これは「競合状態」ではなく、ブラウザ ベースの認証がどのように機能するかの副作用として特徴付けることができます。ここには 3 つの「アクター」が関与しています。

  1. あなたの申請
  2. フェイスブック
  3. ユーザー

ユーザーがアプリケーションにアクセスしたとき、Facebook はまだプロセスに関与していません。これは、ユーザーがアプリケーションで既に承認されている Facebook ユーザーであるかどうかがわからないことを意味します。Facebook はまだあなたに通知する機会がないためです。これが、最初のリクエストで Cookie を取得しない理由です。

アプリケーションがこのリクエストに応答すると、Facebook JavaScript が含まれます。JavaScript SDKは、IFrame を使用してバックグラウンドで Facebook に ping を実行し (オプションstatus: trueまたはより明示的に指定した場合)、Facebook に現在サインインしているユーザー (存在する場合) に基づいて応答を取得します。この時点で、セッションが返された場合 (つまり、過去にアプリケーションを承認したサインインしたユーザーがいる場合)、Facebook JavaScript SDKは Cookie を設定します (オプションを使用してそうするように指示したcookie: true場合)。

これが、最初のリクエストで Cookie が取得されない理由の背後にあるロジックです。Cookie の設定に加えて、特定のアクションを実行できるようにするJavaScript イベントを介してこれを通知することもできます。最も一般的なアクションは、単にページをリロードして、サーバーが新たに設定された Cookie を認識し、適切なサインイン ビューをレンダリングできるようにすることです。しかし、もう 1 つのオプションは、Ajax を使用して、ページ全体をリロードする必要のない、より手の込んだことを行うことです。

2 番目のページの読み込み時にのみ発生する理由については、よくわかりません。しかし、これが機能するように設計されている方法です:)

注:文書化されていないがサポートされているエンド ポイント (JavaScript SDK が使用するものと同じもの) への完全なページ リダイレクトを含む、高度な使用シナリオには踏み込みませんでした。JavaScript SDK を使用することを強くお勧めします。なぜなら、JavaScript SDK の方がはるかにシンプルで、一般的によりパフォーマンスの高いソリューションをわずかなユーザビリティ コストで提供するからです。しかし、あなたが十分に気にかけているなら、私はそれについても詳しく説明できます.

于 2010-07-19T23:09:57.390 に答える
0

競合状態 (Facebook へのユーザー ログイン) へのエントリ ポイントを制御できないため、実行できるオプションの数は限られています。

  1. ステップ 3 で遅延を追加します (おそらく、数ミリ秒のスリープにより、Facebook がサインインするのに十分な時間が得られます)。これは、部分的な修正の厄介な影響をもたらします。「ほとんどの」ケースで機能し、すべてのログインで遅延が発生します。

  2. ステップ 3 で認証が失敗した場合は、数ミリ秒待ってから (正しい量を見つけるためのテスト)、再度認証を試みます。その後、認証されていないページを表示します。

  3. これがページのライフサイクルの問題である場合 (可能性は低い)、ログイン ページに追加のページ/リダイレクトを追加します。つまり、プロセスは次のようになります。

    a) ユーザーが Facebook にログイン
    b) ユーザーがサイトに移動 (Cookie はまだ設定されていません)
    c) ユーザーがログイン ページにリダイレクトされます (Cookie が設定されている場合があります)。ユーザーがまだ認証されていない場合は、100 ミリ秒待ってからステップ b) にリダイレクトします (1 回のみ)。
    d) ユーザーがログインしている

于 2010-07-19T07:00:46.307 に答える
0

私は同じ問題を抱えていました。ページのリロードが機能する理由は、FB.init() が再度呼び出されるためです (これは、実際に Cookie を設定する関数であると思われます)。

そのため、ページをリロードしなくても同じ効果を得ることができます。ここに私が書いたものの様式化されたバージョンがあります。それが「正しい」方法かどうかはわかりませんが、確かに機能します...

FB.getLoginStatus(function(response) {
    if (response.session) {
       window.location.href = '/connect/cb/fb'; 
    }
    else{
       FB.login( function(resp){FBResponse(resp);},perms);
    }
});

var FBResponse = function(response,stop){ if (response.session){ window.location.href = '/connect/cb/fb'; } else{ if (stop) return; FB.init({appId:FBappId, status:true, cookie:true, xfbml:true}); FB.getLoginStatus(function(resp){FBResponse(resp,'stop');}); }; }

于 2010-08-18T18:16:41.233 に答える