我迷失了使用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 });
}
}
我现在的问题是:
拜托,我需要一些明确的指导,因为我现在很困惑,我真的很想建立优秀的代码,我认为情况并非如此。
答案 0 :(得分:4)
对于某些人来说,拥有一个用于身份的DbContext和其他应用程序的DbContext被认为是一种很好的做法。但这不是强制性的,我认为没有必要。我需要2个DbContext吗?
你不应该有大的dbcontexts,较小的上下文更快。这意味着有时您必须创建多个dbcontext。我相信每个上下文中有50个实体就足够了。
我是否正确地将用户与客户端实体相关联?
你不是(在我看来)。 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>
我需要创建一个包含所有用户和附加信息的列表 我从2 DbContext中读取信息?
是的,你可能会,但我不认为这是一个很大的性能交易,因为它不会引起任何额外的数据库查询,因为你当时只使用了1个dbcontext。 / p>
你喜欢干净的代码吗?所以,这里有我的提示(基于我的观点):忘记关于ASP.NET IDENTITY!身份是一个糟糕的解决方案,它不会分离,混淆和不必要。拜托,我需要一些明确的指导,因为我现在很困惑 我真的很想建立优秀的代码,我认为情况并非如此。
您可以使用自定义用户实体创建自己的登录系统。使用此https://crackstation.net/hashing-security.htm#aspsourcecode来散列密码,并使用此MVC Authentication - Easiest Way创建OWIN身份验证
答案 1 :(得分:4)
ASP.NET Identity 2.0非常灵活,同时还提供了一些在mose情况下可以执行的下降默认实现。 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。在后一种情况下,您必须如您所发现的那样更改身份模型中的“几乎所有内容”。虽然我认为你可以不用实现自己的ApplicationRole
。应该可以将ApplicationUser
声明为
public class ApplicationUser: IdentityUser<int, IdentityUserLogin<int>, IdentityUserRole<int>....>
在大多数情况下,单个DbContext
适用于某个应用程序。如果使用多个DbContexts,则它们应该用于彼此不相关的不同的不同数据集。当您将Client
课程设置为与ApplicationUser
相关时,他们应该都在同一个DbContext
。模板试图通过命名DbContext
来传达应用程序上下文的主IdentityDbContext<>
应继承ApplicationDbContext
的想法。使用那个,并用你自己的东西扩展它。我通常将其重命名并将其移至其他地方,但我仍然只有一个DbContext
并让它继承IdentityDbContext<>
。
除非你真的,真的知道你在做什么 - 不要推出自己的身份解决方案。使用已通过外部审核加强安全性的现有项目。如果您对ASP.NET身份不满意,可以查看Brock Allen's Identity reboot。
为了可信度(是的,我今天是赏金猎人):The official ASP.NET documentation链接到我的blog。