【问题标题】:Asp Net Identity - Claim vs Customized IdentityUserAsp Net Identity - 声明与自定义 IdentityUser
【发布时间】:2021-12-17 01:44:51
【问题描述】:

我对自定义用户配置文件以便在应用程序中实现自定义逻辑的最佳方式有点困惑。

假设您必须使用这种属性来分析用户:

  • 等级
  • 可以处理
  • 可以离线工作
  • 可以发送电子邮件
  • canViewFullName

我必须在哪里实现这种属性? 我必须自定义 IdentityUser(使用 ApplicationUser)还是必须创建自定义声明?

【问题讨论】:

    标签: c# attributes asp.net-identity claims


    【解决方案1】:

    这两种方法都是可行的,有人可能会说这是一个偏好问题。

    我会说在 IdentityUser 实现中只使用添加的属性更容易访问并且需要更少的代码。

    性能方面,我认为需要添加的用户和数据越多,属性和数据库存储就越好,使用 cookie 可以更快,但取决于大量数据的使用和服务器配置特别是如果您想为每个用户存储大量信息,从长远来看会更好。

    您还必须考虑数据持久性 如果以下一项为真,则必须使用属性。

    • 数据需要无限期存储
    • 如果用户未登录,则可以或必须访问数据。

    之后,这实际上是您的应用程序中的品味和特定需求问题。

    考虑到您的示例,您只能使用 IdentityUser 属性:

    public class ApplicationUser : IdentityUser
    {
        public async Task<ClaimsIdentity>GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            var userIdentity = await manager.CreateIdentityAsync(this,  DefaultAuthenticationTypes.ApplicationCookie);
            return userIdentity;
        }
    
        //There you can use display name or any attributes like a regular Model.
        public LevelEnum Level { get; set; }
        [Display(Name = "Is allowed to process")]
        public bool CanProcess { get; set; }
        public bool CanWorkOffline { get; set; }
        public bool CanSendEmail { get; set; }
        public bool CanViewFullName { get; set; }
    }
    

    那么您就可以非常轻松地访问控制器中的属性:

    var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
    viewModel.Level = user.Level;
    

    设置方法相同

    user.Level = viewModel.Level;
    

    并使用 UserManager 保存用户:

    await _userManager.UpdateAsync(user);
    //or to create
    await UserManager.CreateAsync(user, model.Password);
    

    关于理赔方式:

        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
    
            // Add custom user claims here 
            userIdentity.AddClaim(new Claim("Level", LevelEnum.Default));
    
            return userIdentity;
        }
    

    然后访问:

    //claim can be null.
    var claim = ((ClaimsIdentity)identity).FirstOrDefault("Level") ?? LevelEnum.Default;
    

    当然,如果需要,您可以将存储的属性分贝到声明中。 使用上面的 Propreties 示例:

        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
    
            // Add custom user claims here 
            userIdentity.AddClaim(new Claim(nameof(Level), Level));
    
            return userIdentity;
        }
    

    【讨论】:

      【解决方案2】:

      (不小心碰到了这个,也许this related answer对某人也有用。)
      由于 Gaelsa 已经 mentioned,这是一个偏好问题。 我想说,我的主要考虑是:

      • ASP.NET 标识作为用户数据主要来源的属性应该是强类型数据库列(通常在 AspNetUsers 中),并在创建主体时传播到声明(必要时)。
      • 从其他来源导入和更新的属性可以立即传播到数据库 (AspNetUsersClaims) 中的声明。

      例子:

      • 如果CanSendEmail 是用户在此身份接口中输入和更改的属性,我会将其存储在AspNetUsers 的强类型数据库列中。
      • 如果CanSendEmail 是在另一个应用程序中维护并从那里更新的属性,我会将其作为记录存储在声明表中,因此存储在AspNetUsersClaims 中。

      FWIW:保存其他用户属性,不会自动将它们添加为声明。您可以通过从UserClaimsPrincipalFactory&lt;TUser&gt; 派生并覆盖CreateAsync(请参阅this answer)在保存时传播它们。
      或者,也许您可​​以在请求和生成声明时添加它(我认为,手头没有示例)。

      【讨论】:

        猜你喜欢
        • 2020-02-01
        • 2014-03-05
        • 2016-11-18
        • 1970-01-01
        • 2020-07-24
        • 1970-01-01
        • 1970-01-01
        • 2019-04-22
        • 2019-12-28
        相关资源
        最近更新 更多