在MVC3中扩展ClaimsIdentity

时间:2012-09-12 09:36:00

标签: asp.net-mvc asp.net-mvc-3 claims-based-identity

我已经使用azure设置了使用MVC3的声明,一切进展顺利。

我现在需要做的是扩展当前线程/ http上下文中的声明身份并添加我自己的信息(DOB,地址......那种东西)

所以我的问题是 - 最好的地方在哪里?任何例子都会很棒..

我认为当用户通过身份验证时,必须转到数据库并撤回用户的相关记录,然后将其添加到自定义的声明身份对象中?

1 个答案:

答案 0 :(得分:21)

通常,您将拥有一个检查cookie的httpmodule,一旦找到FedAuth令牌,您就可以建立自己的声明主体和身份。

您通常不需要存储用户的整个配置文件,只是通常不会改变的有用信息。我在动作过滤器中执行此操作。

以下是我发现的所有这些代码。

https://github.com/wcpro/ScaffR/tree/master/src/ScaffR.Security/content/CodeTemplates/Scaffolders/ScaffR.Security

你可能需要进行一些挖掘,但一切都在那里。

以下是http模块的代码

public class ClaimsTransformationHttpModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PostAuthenticateRequest += context_PostAuthenticateRequest;
    }

    void context_PostAuthenticateRequest(object sender, EventArgs e)
    {
        var context = ((HttpApplication) sender).Context;

        if (FederatedAuthentication.SessionAuthenticationModule != null &&
            FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(context.Request.Cookies))
        {
            return;
        }

        var transformer = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager;

        if (transformer != null)
        {
            var transformedPrincipal = transformer.Authenticate(context.Request.RawUrl, context.User as ClaimsPrincipal);

            context.User = transformedPrincipal;
            Thread.CurrentPrincipal = transformedPrincipal;
        }
    }

    public void Dispose() { }
}

这是Claims Transformer

    public partial class ClaimsTransformer : ClaimsAuthenticationManager
{
    partial void SetCustomPrincipalClaims(IUserService userService, ref ClaimsPrincipal principal);

    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
        if (!incomingPrincipal.Identity.IsAuthenticated)
        {
            return incomingPrincipal;
        }

        var newPrincipal = Transform(incomingPrincipal);

        EstablishSession(newPrincipal);

        return newPrincipal;
    }

    ClaimsPrincipal Transform(ClaimsPrincipal incomingPrincipal)
    {
        var nameClaim = incomingPrincipal.Identities.First().FindFirst(ClaimTypes.Name);

        var userService = DependencyResolver.Current.GetService<IUserService>();

        var user = userService.GetByUsername(nameClaim.Value);

        var id = new ApplicationIdentity(user);

        var principal = new ClaimsPrincipal(id);

        SetCustomPrincipalClaims(userService, ref principal);

        return principal;
    }        

    private void EstablishSession(ClaimsPrincipal principal)
    {
        if (HttpContext.Current != null)
        {
            var sessionToken = new SessionSecurityToken(principal);
            FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
        }
    }
}

然后是配置

<?xml version="1.0" encoding="utf-8"?>
<system.identityModel>
  <identityConfiguration>
    <claimsAuthenticationManager type="Barbarella.Core.Common.Security.ClaimsTransformer, Barbarella.Core" />
  </identityConfiguration>
</system.identityModel>

这就是......

    <system.identityModel.services>
  <federationConfiguration>
    <cookieHandler mode="Default" requireSsl="false" />
  </federationConfiguration>
</system.identityModel.services>

这就是......

<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
  <add name="ClaimsTransformationModule" type="Barbarella.Core.Common.Security.ClaimsTransformationHttpModule, Barbarella.Core" />
  <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

</modules>

别忘了添加配置部分

    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />

这是我的ApplicationIdentity代码(覆盖ClaimsIDentity)......这是真正回答你问题的代码......

 public sealed partial class ApplicationIdentity : ClaimsIdentity
{
    partial void SetCustomIdentityClaims(User user);

    private readonly User _user;

    public ApplicationIdentity(User user) : base("Application")
    {
        _user = user;
        AddClaim(new Claim(ClaimTypes.Name, user.Username));     
        AddClaim(new Claim(ApplicationClaimTypes.UserId, user.Id.ToString(CultureInfo.InvariantCulture)));
        AddClaim(new Claim(ApplicationClaimTypes.FirstName, user.FirstName));
        AddClaim(new Claim(ApplicationClaimTypes.LastName, user.LastName));
        AddClaim(new Claim("Time", DateTime.Now.ToString()));

        SetCustomIdentityClaims(_user);
    }

    public User User
    {
        get { return _user; }
    }

    public int UserId
    {
        get { return int.Parse(FindFirst(ApplicationClaimTypes.UserId).Value); }
    }

    public string Username
    {
        get { return FindFirst(ClaimTypes.Name).Value; }
    }

}