3

ユーザーがパッシブacsを使用してアプリケーションにサインオンしたことを検出できるようにしたいので、アプリを初めて使用する場合にデータベースに追加できます。現在、WSFederationAuthenticationModule.SignedInを購読していますが、何かが足りないと感じています。主に、イベントをサブスクライブするのに最適な場所がわかりません。PostAuthenticateRequest内で機能するようになりましたが、少しハッキーです。助言がありますか?

このコードは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
    }

編集:

今のところ、フラグ変数を使用して、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   

    }

編集: もう少し情報。この問題は、Azureエミュレーターを使用している場合に発生します。おそらく、デプロイされたときにも発生しますが、試したことはありません。テキストファイルに書き込もうとしてデバッグできず、テキストファイルが作成されていないかどうかをテストしました。

4

2 に答える 2

6

PostAuthenticateRequestイベントが発生するたびにSignedInイベントをサブスクライブするのはなぜですか?アプリケーションの起動時に(Global.asaxで)簡単にサブスクライブでき、サインインしたユーザーごとに発生します。

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

SignedInイベントは、アプリケーションを続行する前にユーザーのサインインを検出するための最良の方法です。次の図を見てください。ページにリダイレクトする前に、SignedInイベントが発生し、ユーザーのサインインを検出できるようになります。

フェデレーション認証モジュールの図

参照: http: //msdn.microsoft.com/en-us/library/ee517293.aspx

于 2012-05-12T15:43:37.760 に答える
2

ClaimsAuthenticationManagerから派生するクラスを作成しました。オーバーライドする必要があるメソッドは1つだけです。それは、

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" />

このトリックは、 WindowsAzureMarketplaceにあるサンプルアプリから学びました。Window Azure Marketplaceで公開する予定がない場合でも、ACS統合に使用できるいくつかの役立つコードスニペットを含む優れたサンプルです。

于 2012-05-14T22:16:28.210 に答える