正确使用Microsoft.AspNet.Identity 2.0

时间:2015-12-04 23:58:38

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

我迷失了使用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中读取信息?

拜托,我需要一些明确的指导,因为我现在很困惑,我真的很想建立优秀的代码,我认为情况并非如此。

2 个答案:

答案 0 :(得分:4)

  

我需要2个DbContext吗?

对于某些人来说,拥有一个用于身份的DbContext和其他应用程序的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)

ApplicationUser上的Id类型

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>....>

DbContexts

在大多数情况下,单个DbContext适用于某个应用程序。如果使用多个DbContexts,则它们应该用于彼此不相关的不同的不同数据集。当您将Client课程设置为与ApplicationUser相关时,他们应该都在同一个DbContext。模板试图通过命名DbContext来传达应用程序上下文的主IdentityDbContext<>应继承ApplicationDbContext的想法。使用那个,并用你自己的东西扩展它。我通常将其重命名并将其移至其他地方,但我仍然只有一个DbContext并让它继承IdentityDbContext<>

滚动您自己的身份解决方案

除非你真的,真的知道你在做什么 - 不要推出自己的身份解决方案。使用已通过外部审核加强安全性的现有项目。如果您对ASP.NET身份不满意,可以查看Brock Allen's Identity reboot

为了可信度(是的,我今天是赏金猎人):The official ASP.NET documentation链接到我的blog