ASP.NET 标识我的模式
ASP.NET Identity my schema
我已经有 DB,需要添加 ASP.NET 身份。我的 AspNetUser class:
public partial class AspNetUser
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public AspNetUser()
{
AspNetUserClaims = new HashSet<AspNetUserClaim>();
AspNetUserLogins = new HashSet<AspNetUserLogin>();
AspNetRoles = new HashSet<AspNetRole>();
}
public string Id { get; set; }
public string UserName { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public int? CompanyId { get; set; }
public string FullName { get; set; }
[Required]
[StringLength(128)]
public string Discriminator { get; set; }
public string SMSnumber { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AspNetUserClaim> AspNetUserClaims { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AspNetUserLogin> AspNetUserLogins { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AspNetRole> AspNetRoles { get; set; }
}
然后是我的 ApplicationDbContext 上下文:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("MainContext", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
连接字符串:
<add name="MainContext" connectionString="data source=server;initial catalog=3md_maindb_remote;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
应用程序用户class:
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;
}
public int CompanyId { get; set; }
public string SMSnumber { get; set; }
public string FullName { get; set; }
}
应用程序用户管理器:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = false
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
当我尝试登录时,出现错误:
Exception Details: System.Data.SqlClient.SqlException: Invalid column
name 'Email'. Invalid column name 'EmailConfirmed'. Invalid column
name 'PhoneNumber'. Invalid column name 'PhoneNumberConfirmed'.
Invalid column name 'TwoFactorEnabled'. Invalid column name
'LockoutEndDateUtc'. Invalid column name 'LockoutEnabled'. Invalid
column name 'AccessFailedCount'.
此外,我有 MainContext:
public partial class MainContext : DbContext
{
public MainContext()
: base("name=MainContext")
{
}
public virtual DbSet<AspNetRole> AspNetRoles { get; set; }
public virtual DbSet<AspNetUserClaim> AspNetUserClaims { get; set; }
public virtual DbSet<AspNetUserLogin> AspNetUserLogins { get; set; }
public virtual DbSet<AspNetUser> AspNetUsers { get; set; }
据我所知,我需要使用我的 MainContext 而不是 ApplicationDbContext(使用我的架构),但不明白如何...
因为 ApplicationDbContext
是开箱即用的 DbContext
。您的项目中不需要任何其他 DbContext
。因此,只需在您的项目中完全删除 MainContext
Class 并将您自己的实体放入 ApplicationDbContext
class 中。
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("MainContext", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
// put your extra entities here like this.
public IDbSet<MyEntity> MyEntites { get; set;}
// don't put Identity related entities like AspNetRoles. Since already added
}
您可以在同一数据库上使用多个上下文。 Identity Context 开箱即用。如果你不需要改变它,那就不要。仅将身份表用于身份。
您不需要在标识上下文中定义表。只需添加 ApplicationDbContext。您可以使用与 MainContext 相同的连接字符串:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("name=MainContext")
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
您真的不应该将所有表都添加到 IdentityContext 中,因为那不是它们应该在的地方。尽管这些表可能在同一个数据库中,但两个上下文彼此无关。
让您拥有 MainContext 中的表,并且不要超出上下文,除了您可以引用(仅值,而不是数据库引用)IdentityUser 到您的 MainContext.User 的列。从 MainContext 中删除 AspNet... 表。
您不能使用 class AspNetUser。所以你也可以删除它。请改用 ApplicationUser class。要克服缺少字段的问题,请使用:
public class ApplicationUser : IdentityUser
{
[NotMapped]
public override bool EmailConfirmed { get => base.EmailConfirmed; set => base.EmailConfirmed = value; }
// etc.
}
这将忽略缺失的列。请记住,属性存在于代码中并将具有默认值。尽管我认为您的代码实际上并不依赖于这些属性。
如果 MainContext 给您带来麻烦,您可以使用相同的实体对象创建您自己的上下文。您可以在同一数据库上创建多个上下文,仅包括使用过的表,即使您使用单独的程序集也是如此。
我已经有 DB,需要添加 ASP.NET 身份。我的 AspNetUser class:
public partial class AspNetUser
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public AspNetUser()
{
AspNetUserClaims = new HashSet<AspNetUserClaim>();
AspNetUserLogins = new HashSet<AspNetUserLogin>();
AspNetRoles = new HashSet<AspNetRole>();
}
public string Id { get; set; }
public string UserName { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public int? CompanyId { get; set; }
public string FullName { get; set; }
[Required]
[StringLength(128)]
public string Discriminator { get; set; }
public string SMSnumber { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AspNetUserClaim> AspNetUserClaims { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AspNetUserLogin> AspNetUserLogins { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AspNetRole> AspNetRoles { get; set; }
}
然后是我的 ApplicationDbContext 上下文:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("MainContext", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
连接字符串:
<add name="MainContext" connectionString="data source=server;initial catalog=3md_maindb_remote;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
应用程序用户class:
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;
}
public int CompanyId { get; set; }
public string SMSnumber { get; set; }
public string FullName { get; set; }
}
应用程序用户管理器:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = false
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
当我尝试登录时,出现错误:
Exception Details: System.Data.SqlClient.SqlException: Invalid column name 'Email'. Invalid column name 'EmailConfirmed'. Invalid column name 'PhoneNumber'. Invalid column name 'PhoneNumberConfirmed'. Invalid column name 'TwoFactorEnabled'. Invalid column name 'LockoutEndDateUtc'. Invalid column name 'LockoutEnabled'. Invalid column name 'AccessFailedCount'.
此外,我有 MainContext:
public partial class MainContext : DbContext
{
public MainContext()
: base("name=MainContext")
{
}
public virtual DbSet<AspNetRole> AspNetRoles { get; set; }
public virtual DbSet<AspNetUserClaim> AspNetUserClaims { get; set; }
public virtual DbSet<AspNetUserLogin> AspNetUserLogins { get; set; }
public virtual DbSet<AspNetUser> AspNetUsers { get; set; }
据我所知,我需要使用我的 MainContext 而不是 ApplicationDbContext(使用我的架构),但不明白如何...
因为 ApplicationDbContext
是开箱即用的 DbContext
。您的项目中不需要任何其他 DbContext
。因此,只需在您的项目中完全删除 MainContext
Class 并将您自己的实体放入 ApplicationDbContext
class 中。
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("MainContext", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
// put your extra entities here like this.
public IDbSet<MyEntity> MyEntites { get; set;}
// don't put Identity related entities like AspNetRoles. Since already added
}
您可以在同一数据库上使用多个上下文。 Identity Context 开箱即用。如果你不需要改变它,那就不要。仅将身份表用于身份。
您不需要在标识上下文中定义表。只需添加 ApplicationDbContext。您可以使用与 MainContext 相同的连接字符串:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("name=MainContext")
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
您真的不应该将所有表都添加到 IdentityContext 中,因为那不是它们应该在的地方。尽管这些表可能在同一个数据库中,但两个上下文彼此无关。
让您拥有 MainContext 中的表,并且不要超出上下文,除了您可以引用(仅值,而不是数据库引用)IdentityUser 到您的 MainContext.User 的列。从 MainContext 中删除 AspNet... 表。
您不能使用 class AspNetUser。所以你也可以删除它。请改用 ApplicationUser class。要克服缺少字段的问题,请使用:
public class ApplicationUser : IdentityUser
{
[NotMapped]
public override bool EmailConfirmed { get => base.EmailConfirmed; set => base.EmailConfirmed = value; }
// etc.
}
这将忽略缺失的列。请记住,属性存在于代码中并将具有默认值。尽管我认为您的代码实际上并不依赖于这些属性。
如果 MainContext 给您带来麻烦,您可以使用相同的实体对象创建您自己的上下文。您可以在同一数据库上创建多个上下文,仅包括使用过的表,即使您使用单独的程序集也是如此。