正确使用Microsoft.AspNet.Identity 2.0
Correct use of Microsoft.AspNet.Identity 2.0
我迷失了使用 MVC 5 模板附带的身份验证方法。
我需要将 CreateBy 用户包含在一个名为 client 的实体中,所以经过一番研究后我得出了这个结论:
型号:
[Table("Clients")]
public partial class Client
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public virtual int UserCreated_Id { get; set; }
[ForeignKey("UserCreated_Id")]
public virtual ApplicationUser UserCreated { get; set; }
}
控制器方法:
client.UserCreated_Id = User.Identity.GetUserId<int>();
但我不得不更改身份模型中的几乎所有内容:
来自
public class ApplicationUser : IdentityUser
到
public class ApplicationUser : IdentityUser<int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
因此有将近 30 个变化。
但现在我有 2 个 DbContext:
身份上下文:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
public ApplicationDbContext() : base("IPDB") {}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
我的申请背景:
public class MyDbContext : DbContext
{
public MyDbContext() : base("IPDB")
{
// Tells Entity Framework that we will handle the creation of the database manually for all the projects in the solution
Database.SetInitializer<MyDbContext>(null);
}
public DbSet<Client> Clients { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ANOTHER CHANGE I HAD TO MADE TO BE ABLE TO SCAFFOLDING
modelBuilder.Entity<ApplicationUserLogin>().HasKey<int>(l => l.UserId);
modelBuilder.Entity<ApplicationRole>().HasKey<int>(r => r.Id);
modelBuilder.Entity<ApplicationUserRole>().HasKey(r => new { r.RoleId, r.UserId });
}
}
我现在的问题是:
- 我需要 2 个 DbContext 吗?
- 我是否正确地将用户与客户端实体相关联?
- 我需要创建所有用户的列表和其他信息,我可以从 2 DbContext 中读取信息吗?
拜托,我需要一些清晰的指南,因为我现在很困惑,我真的很喜欢构建出色的代码,但我认为情况并非如此。
Do I need 2 DbContext?
对某些人来说,为 Identity 和应用程序的其余部分使用 DbContext 被认为是一种很好的做法。但是这不是强制性的,我认为没有必要。
你不应该有大的 dbcontexts,较小的上下文更快。这意味着有时您必须创建多个 dbcontext。我相信每个上下文 50 个实体应该足够了。
Am I associating the user to the client entity correctly?
你不是(在我看来)。 ApplicationUser
使用 Guid
(默认情况下)表示其主键值,而不是 Int32
。所以,而不是这个:
public virtual int UserCreated_Id { get; set; }
[ForeignKey("UserCreated_Id")]
public virtual ApplicationUser UserCreated { get; set; }
你应该使用这个(记得在 UserCreated_Id
中删除虚拟):
public Guid UserCreated_Id { get; set; }
[ForeignKey("UserCreated_Id")]
public virtual ApplicationUser UserCreated { get; set; }
在您的上下文中,这应该足够了:
public class ApplicationUser : IdentityUser
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
I need to create a list of all users, and aditional information, will
I read the information from 2 DbContext?
是的,你可能会,但我认为这不是什么大的性能问题,因为它不会导致任何额外的数据库查询,考虑到你当时只使用 1 个 dbcontext。
Please, I need some clear guide because I am very confused right now
and I really love to build great code, and I think it's not the case.
你喜欢简洁的代码吗?所以,这是我的提示 (基于我的意见):忘记 ASP.NET 身份! Identity 是一个糟糕的解决方案,它没有解耦、混乱和不必要。
您可以使用自定义用户实体创建自己的登录系统。使用此 https://crackstation.net/hashing-security.htm#aspsourcecode for hashing the passwords and this 创建 OWIN 身份验证
ApplicationUser 的 ID 类型
ASP.NET Identity 2.0 非常灵活,同时还提供了一些在大多数情况下都可以使用的默认实现。 MVC 5 模板在大多数地方使用默认实现,但在某些情况下添加了一些额外的东西以使定制更容易。
内部 ASP.NET 身份始终使用 IdentityUser<...>
。所有这些模板参数都提供了一种选择您自己的密钥类型的方法,这意味着您还必须选择您自己的 IdentityUserRole 类型(因为它包含密钥)。
还有使用字符串作为键的便捷默认实现。字符串的值是 GUID 的字符串表示形式。
public class IdentityUser :
IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUser, IUser<string>
{
/// <summary>
/// Constructor which creates a new Guid for the Id
/// </summary>
public IdentityUser()
{
this.Id = Guid.NewGuid().ToString();
}
将字符串作为数据库中的主键并不常见,但对于安全敏感的东西来说这是有意义的。在数据库之间复制的数据不会有 ID 冲突的风险,不会给用户错误的权限。
在您的情况下,您需要选择:使用带有字符串 PK 的默认实现或将 id 更改为 int。在后一种情况下,您必须按照您发现的那样更改身份模型中的 "almost everything" 。尽管我认为您可以不实现自己的 ApplicationRole
。应该可以将 ApplicationUser
声明为
public class ApplicationUser: IdentityUser<int, IdentityUserLogin<int>, IdentityUserRole<int>....>
数据库上下文
在大多数情况下,单个 DbContext
就可以满足应用程序的要求。如果使用多个 DbContext,它们应该用于彼此不相关的不同数据集。当您将 Client
class 设置为与 ApplicationUser
相关时,它们应该在同一个 DbContext
中。该模板试图通过将其命名为 ApplicationDbContext
来传达应用程序上下文的主要 DbContext
应该继承 IdentityDbContext<>
的思想。使用那个,并用你自己的东西扩展它。我通常会重命名它并将它移动到其他地方,但我仍然只有一个 DbContext
并让它继承 IdentityDbContext<>
.
推出您自己的身份解决方案
除非你真的、真的知道你在做什么 - 不要推出你自己的身份解决方案。使用已通过外部审查加强安全性的现有产品。如果您对 ASP.NET Identity 不满意,可以查看 Brock Allen's Identity reboot.
为了可信度(是的,我今天是赏金猎人):The official ASP.NET documentation links to my blog.
我迷失了使用 MVC 5 模板附带的身份验证方法。
我需要将 CreateBy 用户包含在一个名为 client 的实体中,所以经过一番研究后我得出了这个结论:
型号:
[Table("Clients")]
public partial class Client
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public virtual int UserCreated_Id { get; set; }
[ForeignKey("UserCreated_Id")]
public virtual ApplicationUser UserCreated { get; set; }
}
控制器方法:
client.UserCreated_Id = User.Identity.GetUserId<int>();
但我不得不更改身份模型中的几乎所有内容:
来自
public class ApplicationUser : IdentityUser
到
public class ApplicationUser : IdentityUser<int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
因此有将近 30 个变化。
但现在我有 2 个 DbContext:
身份上下文:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
public ApplicationDbContext() : base("IPDB") {}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
我的申请背景:
public class MyDbContext : DbContext
{
public MyDbContext() : base("IPDB")
{
// Tells Entity Framework that we will handle the creation of the database manually for all the projects in the solution
Database.SetInitializer<MyDbContext>(null);
}
public DbSet<Client> Clients { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ANOTHER CHANGE I HAD TO MADE TO BE ABLE TO SCAFFOLDING
modelBuilder.Entity<ApplicationUserLogin>().HasKey<int>(l => l.UserId);
modelBuilder.Entity<ApplicationRole>().HasKey<int>(r => r.Id);
modelBuilder.Entity<ApplicationUserRole>().HasKey(r => new { r.RoleId, r.UserId });
}
}
我现在的问题是:
- 我需要 2 个 DbContext 吗?
- 我是否正确地将用户与客户端实体相关联?
- 我需要创建所有用户的列表和其他信息,我可以从 2 DbContext 中读取信息吗?
拜托,我需要一些清晰的指南,因为我现在很困惑,我真的很喜欢构建出色的代码,但我认为情况并非如此。
Do I need 2 DbContext?
对某些人来说,为 Identity 和应用程序的其余部分使用 DbContext 被认为是一种很好的做法。但是这不是强制性的,我认为没有必要。
你不应该有大的 dbcontexts,较小的上下文更快。这意味着有时您必须创建多个 dbcontext。我相信每个上下文 50 个实体应该足够了。
Am I associating the user to the client entity correctly?
你不是(在我看来)。 ApplicationUser
使用 Guid
(默认情况下)表示其主键值,而不是 Int32
。所以,而不是这个:
public virtual int UserCreated_Id { get; set; }
[ForeignKey("UserCreated_Id")]
public virtual ApplicationUser UserCreated { get; set; }
你应该使用这个(记得在 UserCreated_Id
中删除虚拟):
public Guid UserCreated_Id { get; set; }
[ForeignKey("UserCreated_Id")]
public virtual ApplicationUser UserCreated { get; set; }
在您的上下文中,这应该足够了:
public class ApplicationUser : IdentityUser
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
I need to create a list of all users, and aditional information, will I read the information from 2 DbContext?
是的,你可能会,但我认为这不是什么大的性能问题,因为它不会导致任何额外的数据库查询,考虑到你当时只使用 1 个 dbcontext。
Please, I need some clear guide because I am very confused right now and I really love to build great code, and I think it's not the case.
你喜欢简洁的代码吗?所以,这是我的提示 (基于我的意见):忘记 ASP.NET 身份! Identity 是一个糟糕的解决方案,它没有解耦、混乱和不必要。
您可以使用自定义用户实体创建自己的登录系统。使用此 https://crackstation.net/hashing-security.htm#aspsourcecode for hashing the passwords and this
ApplicationUser 的 ID 类型
ASP.NET Identity 2.0 非常灵活,同时还提供了一些在大多数情况下都可以使用的默认实现。 MVC 5 模板在大多数地方使用默认实现,但在某些情况下添加了一些额外的东西以使定制更容易。
内部 ASP.NET 身份始终使用 IdentityUser<...>
。所有这些模板参数都提供了一种选择您自己的密钥类型的方法,这意味着您还必须选择您自己的 IdentityUserRole 类型(因为它包含密钥)。
还有使用字符串作为键的便捷默认实现。字符串的值是 GUID 的字符串表示形式。
public class IdentityUser :
IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUser, IUser<string>
{
/// <summary>
/// Constructor which creates a new Guid for the Id
/// </summary>
public IdentityUser()
{
this.Id = Guid.NewGuid().ToString();
}
将字符串作为数据库中的主键并不常见,但对于安全敏感的东西来说这是有意义的。在数据库之间复制的数据不会有 ID 冲突的风险,不会给用户错误的权限。
在您的情况下,您需要选择:使用带有字符串 PK 的默认实现或将 id 更改为 int。在后一种情况下,您必须按照您发现的那样更改身份模型中的 "almost everything" 。尽管我认为您可以不实现自己的 ApplicationRole
。应该可以将 ApplicationUser
声明为
public class ApplicationUser: IdentityUser<int, IdentityUserLogin<int>, IdentityUserRole<int>....>
数据库上下文
在大多数情况下,单个 DbContext
就可以满足应用程序的要求。如果使用多个 DbContext,它们应该用于彼此不相关的不同数据集。当您将 Client
class 设置为与 ApplicationUser
相关时,它们应该在同一个 DbContext
中。该模板试图通过将其命名为 ApplicationDbContext
来传达应用程序上下文的主要 DbContext
应该继承 IdentityDbContext<>
的思想。使用那个,并用你自己的东西扩展它。我通常会重命名它并将它移动到其他地方,但我仍然只有一个 DbContext
并让它继承 IdentityDbContext<>
.
推出您自己的身份解决方案
除非你真的、真的知道你在做什么 - 不要推出你自己的身份解决方案。使用已通过外部审查加强安全性的现有产品。如果您对 ASP.NET Identity 不满意,可以查看 Brock Allen's Identity reboot.
为了可信度(是的,我今天是赏金猎人):The official ASP.NET documentation links to my blog.