正确使用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 });
    }
}

我现在的问题是:

拜托,我需要一些清晰的指南,因为我现在很困惑,我真的很喜欢构建出色的代码,但我认为情况并非如此。

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.