2012-05-12 4 views
3

パッシブACを使用してユーザーが自分のアプリケーションにサインオンしたときを検出できるようにするため、アプリを初めて使用する場合はデータベースに追加できます。今はWSFederationAuthenticationModule.SignedInを購読していますが、私は何か不足していると感じています。主にイベントに登録するのに最適な場所がわからないので、PostAuthenticateRequestの内部で作業するようにしましたが、ちょっとハッキリしました。助言がありますか?azure acsとmvc3を使用しているときにユーザーのサインインを検出する最も良い場所は何ですか?

このコードは、Global.asaxのからです

public override void Init() 
    { 

     base.Init(); 

     PostAuthenticateRequest += (s, e) => 
     { 
      try 
      { 
       FederatedAuthentication.WSFederationAuthenticationModule.SignedIn -= SignedIn; 
      } 
      finally 
      { 
       FederatedAuthentication.WSFederationAuthenticationModule.SignedIn += SignedIn; 
      } 

     }; 


    } 


    private void SignedIn(object sender, EventArgs e) 
    { 
     //do something 
    } 

EDIT:今のところ

は私が唯一SignedInに一度購読を確認するためにフラグ変数を使用するつもりです。誰かが他の提案をしていない限り、サンドリーノの助けを借りて感謝します。ここには私の瞬間があります。

private static bool isFirstRequest = true; 

    public override void Init() 
    { 


     base.Init(); 

     PostAuthenticateRequest += (s, e) => { 
     if (isFirstRequest) 
     { 
      FederatedAuthentication 
       .WSFederationAuthenticationModule.SignedIn += SignedIn; 
      isFirstRequest = false; 
     } 

     }; 

    } 


    private void SignedIn(object sender, EventArgs e) 
    { 

     //do something 

    } 

EDIT: もう少し情報。この問題は、私が紺碧のエミュレータを使用している場合に発生します。展開されたときに発生する可能性がありますが、試していません。テキストファイルに書き込もうとするとデバッグできず、テキストファイルが作成されていないかどうかをテストしました。

答えて

6

なぜPostAuthenticateRequestイベントが発生するたびにSignedInイベントを購読していますか? SignedInイベントは、ユーザーのサインを検出するための最良の方法です

public class MvcApplication : System.Web.HttpApplication 
{ 
    ... 

    protected void Application_Start() 
    { 
     ... 

     FederatedAuthentication.ServiceConfigurationCreated += (s, e) => 
     { 
      FederatedAuthentication.WSFederationAuthenticationModule.SignedIn += new EventHandler(OnUserSignedIn); 
     }; 
    } 

    private void OnUserSignedIn(object sender, EventArgs e) 
    { 
     // Custom logic here. 
    } 
} 

:あなたは、単純なアプリケーションは、(Global.asaxの中で)を開始し、それがに署名し、ユーザーごとに発生しますとき、それを購読することができますアプリケーションが続行される前に次の図を見てください。

Federated Authentication Module diagram

参考:バックページにリダイレクトする前に、SignedInイベントはあなたがユーザーのサインを検出できるようにするために発生しhttp://msdn.microsoft.com/en-us/library/ee517293.aspx

+0

私はそれをやろうとしましたが、WsFederationAuthenticationModuleはアプリケーションの起動時にはnullですが、postauthenticate要求の中で利用できます。私は自分のWebの設定が正しいと思う、私はwsfederationmoduleを追加するために手動でそれを編集しなかっただけで、stsの参照ツールを追加しました。 –

+0

コードサンプルを修正しましたが、アプリケーションの起動時にWSFederationAuthenticationModuleがすぐに使用できないことは事実です。 –

+0

まだ動作しませんでしたが、WsFederationAuthenticationModuleはそのイベントで使用できますが、signedinイベントを購読することは効果がなく、すべてのモジュールのプロパティは空です。おそらく、そこで利用可能なモジュールはちょうど初期値であり、パイプラインをさらに下げると、新しいインスタンスがそれを置き換えます。 global.asaxにフラグ変数を置き、それを使ってsignedinを強制的に一度だけ購読するようにします。新しい方法を反映するために質問を編集します。 –

2

私はClaimsAuthenticationManagerから派生するクラスを作成しました。私のアプリで

public virtual IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal); 

であるあなたがオーバーライドする必要が唯一の方法は、認証に成功したユーザは、本当に私のアプリのユーザーであれば、私がチェックするために、このメソッドを使用するには(すなわち、それらは存在してあります私のデータベースに)。そうでない場合は、サインアップページに誘導します。

public override IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal) 
    { 
     if (incomingPrincipal.Identity.IsAuthenticated) 
     { 
      var identity = incomingPrincipal.Identity as IClaimsIdentity;     
      User user = null; 

      // Get name identifier and identity provider 
      var nameIdentifierClaim = identity.Claims.SingleOrDefault(c => c.ClaimType.Equals(ClaimTypes.NameIdentifier, StringComparison.OrdinalIgnoreCase)); 
      var identityProviderClaim = identity.Claims.SingleOrDefault(c => c.ClaimType.Equals(CustomClaimTypes.IdentityProviderClaimType, StringComparison.OrdinalIgnoreCase)); 

      if (nameIdentifierClaim == null || identityProviderClaim == null) 
      { 
       throw new AuthenticationErrorException("Invalid claims", "The claims provided by your Identity Provider are invalid. Please contact your administrator."); 
      } 

      try 
      { 
       //checking the database here... 
       using (var context = new CloudContext()) 
       { 
        user = (from u in context.Users 
          where u.IdentityProvider == identityProviderClaim.Value && 
            u.NameIdentifier == nameIdentifierClaim.Value && 
            !u.Account.PendingDelete 
          select u).FirstOrDefault(); 
       } 
      } 
      catch (System.Data.DataException ex) 
      { 
       Console.WriteLine(ex.Message); 
       if (ex.InnerException != null) 
        Console.WriteLine(ex.InnerException); 
       throw; 
      } 

     } 

     return incomingPrincipal; 
    } 

次に、あなたのweb.configファイルには、あなたがそうとして、<microsoft.identitymodel>領域にセクションを追加します:

 <claimsAuthenticationManager type="CloudAnalyzer.UI.Security.CloudAnalyzerClaimsAuthenticationManager" /> 

私がこのトリックを学んだ

私のクラスには、次のようになりますここにあるサンプルアプリはWindows Azure Marketplaceです。 Window Azure Marketplaceに公開しない場合でも、ACSインテグレーションに使用できる便利なコードスニペットを備えた良いサンプルです。

+0

すごい、私はこれを試してみるつもりです。私がこの時点でコレクションに請求を追加する場合、あなたの頭の上から外して、セキュリティトークンに入れられ、次の要求で利用可能になるでしょうか?私はより多くの研究をするつもりだから、あなたもそれを見る必要があるならば心配はありません。 –

+0

はい、ここにクレームを追加することができます。上記のサンプルでは、​​ユーザーが所属するアカウントである「tenantId」のカスタム要求が追加されています。サンプルには、このパブリックオーバーライドIClaimsPrincipal Authenticateメソッドで実行され、提供されたクレームとカスタムクレームを検証する "UpdateClaims"メソッドがあります。見てみな... – ChrisW

関連する問題