使用 Web Api 身份和令牌时向用户播种数据库的正确方法

Correct way to seed DB with users when using Web Api Identity and Tokens

我有一个 MVC Wab API,我已经开始使用代码优先方法对其进行修改以包含我自己的一些 table。

我在使用初始数据为 AspNetUsers table 播种时遇到问题,这些初始数据随后与我的(默认)基于令牌的身份验证一起使用。

当我为数据库设置种子时,未填充 SecurityStamp 字段,这似乎对基于令牌的身份验证至关重要。 通过 AccountController 注册一个帐户会产生这种罚款,但是当我通过下面的代码看到 table 时,安全标记没有被填充......这是可以理解的。

    context.Users.Add(new ApplicationUser
    {
        Email = "damo2@email.co.uk",
        UserName = "damo2@email.co.uk",
        PasswordHash = new PasswordHasher().HashPassword("Som3Pass!")
    });

似乎有一个 UpdateSecurityStampAsync 方法,我认为它会生成安全标记,但我不知道在播种时如何调用/使用它。 (这里不知道怎么办。。我还是新手)

问题是:

  1. 使用 MVC WebAPI 和个人帐户时,为用户 table 播种的正确方法是什么。

  2. 如果我应该使用 UpdateSecurityStampAsync 方法,怎么办?

对于问题2,步骤是:

在上下文中添加/更新用户。

创建用户存储。 UserStore 基本上是 ASP Identity 的数据层包装器。它控制 ASP Identity 如何与数据库一起工作。

创建一个用户管理器。 UserManager 基本上是 ASP Identity 的实现。 ASP Identity "out of the box" 包含许多方法,其中大部分是空的(例如:SendSMS、VerifyTwoFactorToken)。开发人员应该实现他们关心的方法。

但是,UpdateSecurityStamp 方法是具有默认实现的方法之一。所以我们走运了。

呼叫UserManager.UpdateSecurityStamp(UserJustUpdated.Id).

  public override void Seed(ApplicationDbContext context)
  {
      //The UserStore is ASP Identity's data layer. Wrap context with the UserStore.
      UserStore<ApplicationUser> userStore = new UserStore<ApplicationUser>(context);

      //The UserManager is ASP Identity's implementation layer: contains the methods.
      //The constructor takes the UserStore: how the methods will interact with the database.
      UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(userStore);

      //Add or Update the initial Users into the database as normal.
      context.AddOrUpdate(
          x => x.Email,  //Using Email as the Unique Key: If a record exists with the same email, AddOrUpdate skips it.
          new ApplicationUser() { Email = "damo2@email.co.uk", UserName = "damo2@email.co.uk", PasswordHash = new PasswordHasher().HashPassword("Som3Pass!") },
          new ApplicationUser() { Email = "2ndUser@email.co.uk", UserName = "Jane Doe", PasswordHash = new PasswordHasher().HashPassword("MyPassword") }
      );

      //Save changes so the Id columns will auto-populate.
      context.SaveChanges();

      //ASP Identity User Id's are Guids stored as nvarchar(128), and exposed as strings.

      //Get the UserId only if the SecurityStamp is not set yet.
      string userId = context.Users.Where(x => x.Email == "damo2@email.co.uk" && string.IsNullOrEmpty(x.SecurityStamp)).Select(x => x.Id).FirstOrDefault();

      //If the userId is not null, then the SecurityStamp needs updating.
      if (!string.IsNullOrEmpty(userId)) userManager.UpdateSecurityStamp(userId);

      //Repeat for next user: good opportunity to make a helper method.
      userId = context.Users.Where(x => x.Email == "2ndUser@email.co.uk" && string.IsNullOrEmpty(x.SecurityStamp)).Select(x => x.Id).FirstOrDetault();

      if (!string.IsNullOrempty(userId)) userManager.UpdateSecurityStamp(userId);

      //Continue on with Seed.
  }

就问题1而言,有很多种方法。哪一个 正确 是一个更大的讨论。最有效率?最安全?最少的工作?

播种方法的主要问题是密码为纯文本。您的环境将决定这是否是一个严重的问题。