Asp 网络身份 - 声明与自定义身份用户

Asp Net Identity - Claim vs Customized IdentityUser

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

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

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

这两种方法都是可行的,可以说这是一种偏好问题。

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

在性能方面,我认为需要添加的用户和数据越多,Properties 就越好,因此数据库存储有意义,使用 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;
    }

(不小心运行进入这个,也许this related answer对某人也有用。)
由于 Gaelsa 已经 ,这是一个偏好问题。 我会说,我的主要考虑是:

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

示例:

  • 如果 CanSendEmail 是用户在此身份界面中输入和更改的 属性,我会将其存储在 AspNetUsers.[=35 中的强类型数据库列中=]
  • 如果 CanSendEmail 是在另一个应用程序中维护并从那里更新的 属性,我会将其存储为声明中的记录-table,因此在 AspNetUsersClaims.

FWIW:保存额外的用户属性,不会自动将它们添加为声明。您可以通过从 UserClaimsPrincipalFactory<TUser> 派生并覆盖 CreateAsync(参见 )来在保存时传播它们。
或者您可以在请求和生成索赔时添加它(我认为,手头没有示例)。