【问题标题】:Replace default IdentityDbContext with existing database information用现有的数据库信息替换默认的 IdentityDbContext
【发布时间】:2015-08-19 05:39:06
【问题描述】:

我需要将 ASP.NET Web API 添加到已经有活动用户数据库的系统中。

根据我使用 asp.net 中内置的默认身份的经验,它通常使用代码优先的方法从头开始创建表。这显然不是我正在寻找的方法。

如何将身份模型指向我当前的数据库而不创建新数据库?

我似乎找不到像样的教程或如何在线?

我假设我必须在身份包中的某个位置实现一个接口,以便提供正常操作所需的最少字段。

我想为用户角色和用户身份执行此操作。

我是否先将当前数据库导入代码?

{编辑}

这是我的表格的链接: ERD

【问题讨论】:

  • 您当前的表是否与身份模型表相同?
  • 我不这么认为,它们似乎是身份模型表,但我认为它们是旧的。将它们发布在问题中。
  • @KeithPayne 请查看我的编辑。或以下链接:dropbox.com/s/rhpq0bkgu56u0ah/Auth%20Tables.oxps
  • Microsoft 的 IdentityDbContext 介绍的一个主要失败是每个项目只能有一个启用迁移的 dbcontext,如果您已经有一个 DbContext,那么这个新的 IdentityDbContext 就会发生冲突。映射到我们的模式并不是一个真正可靠/有效的解决方案,它只适用于最简单的场景。我们需要的是一个不指定 DbContext 的身份框架——例如;当前版本的 IdentityDbContext 应该是基于接口的,而不是整个代码库中的分配器当前依赖于具体的 IdentityDbContext 类型。不必要的。惭愧。

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


【解决方案1】:

可以通过覆盖 OnModelCreating 事件来映射 ASP.NET Identity 对象和属性。这看起来像-

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    var user = modelBuilder.Entity<IdentityUser>().HasKey(u => u.Id).ToTable("User", "Users"); //Specify our our own table names instead of the defaults

    user.Property(iu => iu.Id).HasColumnName("Id");
    user.Property(iu => iu.UserName).HasColumnName("UserName");
    user.Property(iu => iu.Email).HasColumnName("EmailAddress").HasMaxLength(254).IsRequired();
    user.Property(iu => iu.IsConfirmed).HasColumnName("EmailConfirmed");
    user.Property(iu => iu.PasswordHash).HasColumnName("PasswordHash");
    user.Property(iu => iu.SecurityStamp).HasColumnName("SecurityStamp");

    user.HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId);
    user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId);
    user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
    user.Property(u => u.UserName).IsRequired();
...

通过对每个实体使用“ToTable”并为每个属性使用“HasColumnName”,您应该能够映射到您自己的架构。

明显的问题是,这只允许您更改列名和表名,而不能更改列类型。

您可以扩展 IdentityUser 类以添加与架构中的其他数据库列匹配的新属性,并且您可以更改用户和角色的主键类型(请参阅http://aspnet.codeplex.com/SourceControl/latest#Samples/Identity/ChangePK/readme.txt),但核心列类型和信息会需要相同。这很可能是密码哈希列的问题,在 ASP.NET Identity 的情况下,它实际上包含哈希和盐。

如果您有现有的用户凭据,您可能需要翻译它们 - 从 SQL 成员身份执行此操作的过程在 http://www.asp.net/identity/overview/migrations/migrating-an-existing-website-from-sql-membership-to-aspnet-identity 提供,并使用 https://aspnet.codeplex.com/SourceControl/latest#Samples/Identity/SQLMembership-Identity-OWIN/Migrations.sql 的脚本

流程的关键点是-

应用程序用户的密码被加密并存储 在数据库中。 SQL 成员资格中使用的加密算法是 与新身份系统中的不同。重用旧的 密码 我们需要在老用户登录时选择性地解密密码 在使用加密时使用 SQL 成员资格算法 新用户的身份算法。

也可以可能在成功登录后使用以前的成员算法暂时保留密码,然后使用明文字符串将密码添加到新的 ASP.NET Identity 密码列中使用 ASP .NET 身份散列和用户管理器机制 - 但在这种情况下,您应该非常小心地传递纯文本凭据。您还应该在成功迁移后销毁以前系统中的(更弱散列的)凭据,以防将来发生违规(并且如果在迁移到散列明显更强的 ASP.NET 身份列后凭据没有更改)。

【讨论】:

  • 非常感谢您的回复。将查看它并提供反馈。
【解决方案2】:

IdentityDbContext 与普通的DbContext 没有什么不同。如果您不希望它创建表,那么您只需将其视为数据库优先(是的,您可能会混淆地拥有一个数据库优先代码优先项目)。

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("ConnectionStringName")
    {
        Database.SetInitializer<ApplicationDbContext>(null);
    }
}

您当然必须将此上下文与您进行迁移的应用程序上下文分开,但现在它将不再尝试创建数据库或生成表。

【讨论】:

    【解决方案3】:

    另一个选项可能是子类化Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext&lt;Models.ApplicationUser&gt;,这显然只适用于您还没有子类化另一个 DbContext 派生类型的情况。

    例如:

    public class MyDbContext : IdentityDbContext<ApplicationUser>, IMyDbContext
    {
        public IDbSet<MyOtherEntity> OtherEntities { get; set; }
        public MyDbContext() : base("MyDb", false)
        {
            Database.SetInitializer<MyDbContext>(null);
        }
        public static DbContext Create()
        {
            return new MyDbContext();
        }
    }
    

    您将需要编辑 Startup.Auth.cs 并更新 app.CreatePerOwinContext 调用以改为引用新 DbContext 类型的 Create() 方法(或任何基于 DI 的分配器)已在您已建立的成熟产品中使用。)请记住,您在此处提供的方法返回的类型是用于未来 Owin 上下文 Get() 调用的类型。

    因此,您还需要编辑 IdentityConfig.cs 以引用 MyDbContext 类型(而不是 ApplicationDbContext)。否则此方法将失败。如果在编辑后,您在此处收到空引用异常,则说明您没有正确编辑 Startup.Auth.cs(请参阅最后一段。)

    您还可以明智地注释掉位于 IdentityModels.cs 中的默认脚手架 ApplicationDbContext,这样其他开发人员将来就不会感到困惑,它还应该可以帮助您识别任何挥之不去的东西参考文献(应该没有。)

    以上对于大多数常见情况应该足够了,如果您现有的数据库架构与默认生成的不同,您可以覆盖OnModelCreating,如@pwdst 接受的答案中所述(除了详细以上。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-13
      相关资源
      最近更新 更多