3

我希望能够检测用户何时使用被动 acs 登录我的应用程序,以便如果这是第一次使用我的应用程序,我可以将它们添加到我的数据库中。现在我正在订阅 WSFederationAuthenticationModule.SignedIn 但我觉得我错过了一些东西。主要是我不确定订阅该事件的最佳位置,我让它在 PostAuthenticateRequest 中工作,但它有点 hacky。有什么建议么?

此代码来自 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。除非有人有任何其他建议:) 感谢 Sandrino 的帮助。这是我目前所拥有的。

    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 的类。只有一种方法必须重写,即

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 集成的有用代码片段。

于 2012-05-14T22:16:28.210 回答