Правильное использование 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>();

Но мне пришлось изменить почти все в модели Identity:

Из

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?

Пожалуйста, мне нужно несколько четкое руководство, потому что я очень смущен прямо сейчас, и мне очень нравится создавать отличный код, и я думаю, что это не так.

Ответ 1

Тип идентификатора на ApplicationUser

ASP.NET Identity 2.0 является очень гибким, а также предлагает некоторые реализации по умолчанию для спуска, которые будут выполняться в случаях с мозаикой. Шаблон MVC 5 использует стандартные реализации в большинстве мест, но в некоторых случаях добавляется дополнительный материал для упрощения настройки.

Внутренне ASP.NET Identity всегда использует 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();
  }

Наличие строки в качестве первичного ключа в базе данных не так уж и распространено, но для чувствительных к безопасности вещей это имеет смысл. Существует никакой риск того, что данные, скопированные между базами данных, будут иметь встречные идентификаторы, что даст пользователям неправильные привилегии.

В вашем случае вам нужно выбрать: Использовать реализацию по умолчанию с строкой PK или изменить идентификатор на int. В последнем случае вы должны изменить "почти все" в модели identity, как вы обнаружили. Хотя я думаю, что вы могли бы обойтись без реализации своего собственного ApplicationRole. Должно быть возможно просто объявить ApplicationUser как

public class ApplicationUser: IdentityUser<int, IdentityUserLogin<int>, IdentityUserRole<int>....>

DbContexts

В большинстве случаев одно приложение DbContext отлично подходит для приложения. Если используется несколько DbContexts, они должны быть для разных разных наборов данных, которые не связаны друг с другом. Поскольку вы создали свой класс Client для связи с ApplicationUser, они должны быть в одном и том же DbContext. Шаблон пытается передать мысль о том, что основной DbContext контекста приложения должен наследовать IdentityDbContext<>, назвав его ApplicationDbContext. Используйте это и расширьте его своими собственными вещами. Я обычно переименовываю его и перемещаю его в другое место, но все же у меня есть только один DbContext и пусть он наследует IdentityDbContext<>.

Перемещение собственного решения для идентификации

Если вы действительно не знаете, что вы делаете, не откатывайте свое собственное решение для идентификации. Используйте существующий, который был защищен от внешних обзоров. Если вас не устраивает ASP.NET Identity, вы можете взглянуть на перезагрузка Brock Allen Identity.

Для достоверности (да, сегодня я охотник за головами): Официальная документация ASP.NET связана с моим .

Ответ 2

Нужен ли мне 2 DbContext?

Наличие DbContext для Identity и других для остальной части приложения считается хорошей практикой для некоторых людей. Однако это не обязательно, и я не думаю, что это необходимо.

У вас не должно быть больших 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 в то время.

Пожалуйста, мне нужно четкое руководство, потому что я очень смущен прямо сейчас и мне очень нравится создавать отличный код, и я думаю, что это не так.

Вам нравится чистый код? Итак, вот мой совет (основанный на моем мнении): ЗАБУДЬТЕ О ИДЕНТИЧНОСТИ ASP.NET! Идентичность - это плохое решение, оно не является развязанным, запутанным и ненужным.

Вы можете создать свою собственную систему входа, используя пользовательский объект пользователя. Используйте https://crackstation.net/hashing-security.htm#aspsourcecode для хэширования паролей и MVC Authentication - самый простой способ для создания аутентификации OWIN