【问题标题】:Extending ClaimsIdentity in MVC3在 MVC3 中扩展 ClaimsIdentity
【发布时间】:2012-09-12 09:36:00
【问题描述】:

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

我现在需要做的是扩展当前线程/http 上下文中的 Claims Identity 并添加我自己的信息(DOB、地址.. 之类的东西)

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

我假设当用户通过身份验证时,必须去数据库并为用户拉回相关记录,然后将其添加到自定义 Claims Identity 对象中?

【问题讨论】:

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


    【解决方案1】:

    通常,您将有一个 httpmodule 来检查 cookie,一旦找到 FedAuth 令牌,您就有一个挂钩来构建您的 Claims Principal 和身份。

    您通常不需要存储用户的整个个人资料,只需要存储通常不会经常更改的有用信息。我在 actionfilter 中执行此操作。

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

    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() { }
    }
    

    这是声明转换器

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

    【讨论】:

    • 这是一个很棒的答案。
    • 这绝对是一个很棒的答案。我想知道的一件事是validateIntegratedModeConfiguration && runAllManagedModulesForAllRequests 是否严格要求?它们在场景中的用途是什么,因为我已经读到将 runAllManagedModulesForAllRequests 设置为 true 可能会产生某种类型的安全问题,尽管我不完全确定为什么
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-14
    相关资源
    最近更新 更多