如何使用自定义属性扩展 IdentityUser

Posted

技术标签:

【中文标题】如何使用自定义属性扩展 IdentityUser【英文标题】:How to extend IdentityUser with custom property 【发布时间】:2017-03-24 19:10:42 【问题描述】:

我正在使用 asp.net Identity 2.0 让用户登录我的网站,其中身份验证详细信息存储在 SQL 数据库中。 Asp.net Identity 已以标准方式实现,可在许多在线教程中找到。

IdentityModels 中的 ApplicationUser 类已扩展为包含自定义属性:

public class ApplicationUser : IdentityUser

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
    
       CookieAuthenticationOptions.AuthenticationType
       var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
       return userIdentity;
    
    //My extended property
    public string Code  get; set; 

当我注册一个新用户时,我在 RegisterBindingModel 中传递了 Code 自定义属性,但我不确定如何将此自定义属性插入到 WebUsers 表中。

我做了如下操作,但实际上并没有将此属性连同用户名和密码一起插入到表中。

var user = new ApplicationUser()  UserName = userName, Email = model.Email, Code=model.Code ;

以及整个函数:

[AllowAnonymous]
[Route("Register")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
    
        if (!ModelState.IsValid)
        
            return BadRequest(ModelState);
        

        var userName = !string.IsNullOrEmpty(model.UserName) ? model.UserName : model.Email;
        //I set it here but it doesn't get inserted to the table.
        var user = new ApplicationUser()  UserName = userName, Email = model.Email, Code=model.Code ;

        IdentityResult result = await UserManager.CreateAsync(user, model.Password);

        if (!result.Succeeded)
        
            return GetErrorResult(result);
        

        return Ok();
    

我错过了什么? 我正在查看类似的问题,但找不到答案。

【问题讨论】:

我觉得你的代码没问题,你确定Code属性是在model参数里面填的吗? 是的,我确定,我检查过了。但是当我检查数据库中的表时,新用户出现了,但代码字段始终是null UserManager是如何定义的?看看github.com/tjoudeh/AspNetIdentity.WebApi 可能您确定您已按照所有步骤正确地向用户添加属性,无论如何我都与描述共享了所有步骤。试试看,我按照以下步骤成功添加了Code字段↓ 【参考方案1】:

如果您按照向用户添加自定义字段的所有步骤操作,您将成功完成任务。

以下是向用户添加自定义字段的所有步骤:

    创建ASP.NET Web Application 确保选择 MVC 并且 AuthenticationIndividual User Accounts

    转到 Models 文件夹 → 打开 IdentityModels.csApplicationUser 类并添加属性:

    public string Code  get; set; 
    
    构建项目 转到 TOOLS 菜单 → Nuget 包管理器 → 单击 包管理器控制台

    键入Enable-Migrations 并按Enter 并等待任务完成。您将看到一条回复:

       Checking if the context targets an existing database...
       Code First Migrations enabled for project WebApplication1.
    

    键入Add-Migration "Code" 并按Enter 并等待任务完成。您将看到一条回复:

    Scaffolding migration 'Code'. The Designer Code for this migration
    file includes a snapshot of your current Code First model. This
    snapshot is used to calculate the changes to your model when you
    scaffold the next migration. If you make additional changes to your
    model that you want to include in this migration, then you can
    re-scaffold it by running 'Add-Migration Code' again.
    

    键入Update-Database 并按Enter 并等待任务完成。您将看到一条回复:

    Specify the '-Verbose' flag to view the SQL statements being applied 
    to the target database.
    Applying explicit migrations: [201611132135242_Code].
    Applying explicit migration: 201611132135242_Code.
    Running Seed method.
    

    在这一步,如果您刷新 SQL Server 对象资源管理器 并转到数据库并查看表,在列下的 dbo.AspNetUsers 下,您将看到 Code 字段。如果您不知道应该查找哪个数据库甚至哪个服务器,请打开 Web.Config 文件并查看如下所示的连接字符串:

    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-WebApplication1-20161114125903.mdf;Initial Catalog=aspnet-WebApplication1-20161114125903;Integrated Security=True"
    providerName="System.Data.SqlClient" />
    

    您可以看到数据源(即 sql server 实例)和一些 .mdf,即数据库名称。

    转到 Models 文件夹 → 打开 AccountViewModels.cs 文件 → RegisterViewModel 类并添加此属性: (在带有 EF6 的 APIv2 中,您可以在 Models 文件夹 → AccountBindingModels 文件 → RegisterBindingModel 类中添加以下行)

    public string Code  get; set; 
    

    转到 Views 文件夹 → Account 文件夹 → 打开 Register.cshtml 文件并在其他字段附近添加此代码,例如在密码下面:

    <div class="form-group">
        @Html.LabelFor(m => m.Code, new  @class = "col-md-2 control-label" )
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Code, new  @class = "form-control" )
        </div>
    </div>
    

    转到 Controllers 文件夹 → 打开 AccountController.cs 文件 → 在 http post Register 操作中,将创建用户的行更改为:

    var user = new ApplicationUser  UserName = model.Email, Email = model.Email,
        Code= model.Code ;
    

    运行项目并转到/Account/Register url 并注册一个新用户。注册用户后,再次进入数据库查看dbo.AspNetUsers表的数据,会看到代码已经保存。

下载

您可以在此处克隆或下载一个工作示例:

r-aghaei/AddPropertyToIdentityUserExample

延伸阅读 - 如何向 IdentityRole 添加自定义属性?

如果您有兴趣了解如何向IdentityRole 添加新属性,请查看How to Add a custom Property to IdentityRole?

【讨论】:

感谢您清晰而详细的回答,我唯一缺少的一步是:#9:“转到模型文件夹→打开AccountViewModels.cs文件→RegisterViewModel类”,on我的AccountViewModels.cs 文件没有RegisterViewModel 类,我应该添加它吗?谢谢! 不客气。你会需要它。如果不需要,从 View 传递的模型中不会有 Code 按照清洁解决方案中的说明进行操作,您将清楚自己在做什么。 我没有从View 传递Code。我从一个完全不同的项目调用 API。 当我通过注册视图注册时,我不会将其作为参数传递。可能是什么问题?非常感谢您的帮助!【参考方案2】:

希望这可能对其他人有所帮助,因为原始帖子已有 1 年以上的历史了

如果已经使用“身份验证个人用户帐户”创建了项目:

在解决方案资源管理器中转到项目>Models>IdentityModels.cs

public class ApplicationUser: IdentityUser 下(应该是第一类)。

之后添加您的自定义属性 public async Task&lt;ClaimsIdentity&gt; GenerateUserIdentityAsync(UserManager&lt;ApplicationUser&gt; manager) 就像我下面的例子:

public class ApplicationUser : IdentityUser

    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
        return userIdentity;
    
    **//add custom properties here - these are just examples**
    public bool SendEmails  get; set; 
    public string FirstName  get; set; 
    public string LastName  get; set; 

然后使用 NuGet 包管理器:

启用迁移(如果您还没有) 添加迁移 [输入] nameYourMigration [输入] (查看迁移文件以确认您的属性将被添加) 更新数据库[输入] 检查您的 AspNetUsers 数据库表以确保正确添加了属性

我希望这会有所帮助..

【讨论】:

【参考方案3】:

我认为主要问题仍然是您没有在 ApplicationUser 类中注册新声明。

我遇到了同样的问题,我在CreateIdentityAsync 后面几行就解决了。

public class ApplicationUser : IdentityUser

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
    
       CookieAuthenticationOptions.AuthenticationType
       var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);

       // Add custom user claims here
        userIdentity.AddClaim(new Claim("Code",this.Code));
       return userIdentity;
    
    //My extended property
    public string Code  get; set; 

【讨论】:

以上是关于如何使用自定义属性扩展 IdentityUser的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 ASP.NET Core 中的 api 控制器更新 IdentityUser 的自定义属性?

Asp.NET Identity IdentityUser 自定义属性导致运行时错误

Microsoft 标识自定义用户、角色、声明继承

使用 linq 从 IdentityUser 列表中检索自定义配置文件数据

从 ASP.net Core 2 中的视图访问自定义 ApplicationUser 属性

无法从PasswordHasher登录种子的自定义IdentityUser