Исходные пользователи и роли MVC 5

95

Я экспериментировал с новым MVC 5, у меня есть несколько моделей, контроллер и настройка представлений с использованием первых миграций кода.

У меня вопрос: как набрать пользователей и роли? В настоящее время я загружаю некоторые справочные данные в свой метод Seed в Configuration.cs. Но мне кажется, что таблицы пользователей и ролей не создаются, пока что-то сначала не попадет в AccountController.

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

Как я могу заполнить таблицы пользователей, ролей и т. Д. Вместе с другими? А не при попадании в контроллер аккаунта?

MrBeanzy
источник

Ответы:

183

Вот пример обычного подхода Seed:

protected override void Seed(SecurityModule.DataContexts.IdentityDb context)
{
    if (!context.Roles.Any(r => r.Name == "AppAdmin"))
    {
        var store = new RoleStore<IdentityRole>(context);
        var manager = new RoleManager<IdentityRole>(store);
        var role = new IdentityRole { Name = "AppAdmin" };

        manager.Create(role);
    }

    if (!context.Users.Any(u => u.UserName == "founder"))
    {
        var store = new UserStore<ApplicationUser>(context);
        var manager = new UserManager<ApplicationUser>(store);
        var user = new ApplicationUser {UserName = "founder"};

        manager.Create(user, "ChangeItAsap!");
        manager.AddToRole(user.Id, "AppAdmin");
    }
}

Я использовал пакетный менеджер "update-database". БД и все таблицы были созданы и заполнены данными.

Валин
источник
3
К методу Seed класса Configuration. Конфигурация - это имя класса по умолчанию для enable-migrations, но вы можете его изменить.
Валин
3
Вы должны использовать 'enable-migrations' в консоли диспетчера пакетов. Он создаст для вас класс конфигурации с методом seed.
Валин
4
@Zapnologica Migrations очень проста в использовании. Он также позволяет вам редактировать таблицы без повторного создания таблиц. Вам нужно ознакомиться с тремя командами, используя консоль диспетчера пакетов NuGet. Enable-Migrations, Add-Migration и update-database. Легкая легкость.
yardpenalty.com
10
Я буквально скопировал и вставил этот код в свой метод Seed в новом веб-приложении mvc 5, а затем запустил update-database в консоли диспетчера пакетов. Он добавляет роль (я вижу ее в таблице AspNetRoles), но когда дело доходит до линейного менеджера.AddToRole (user.Id, «AppAdmin»), я получаю сообщение об ошибке «UserId not found». Если у вас есть идеи, что мне не хватает, я буду очень признателен за информацию.
Том Риган
2
Пропущено context.Users.Add(user);между manager.Create(user, "ChangeItAsap!");и manager.AddToRole(user.Id, "AppAdmin");. Итак, у новорожденного пользователя нет User.Id.
ApceH Hypocrite
15

Это небольшое дополнение, но для всех, у кого есть «UserId not found». сообщение при попытке посеять: (Том Риган задавал этот вопрос в комментариях, и я сам на какое-то время застрял на нем)

Это означает, что manager.Create (пользователь, «ChangeItAsap!») Не удалось. У этого могла быть другая причина, но для меня это было потому, что мой пароль не прошел проверку.

У меня был специальный валидатор паролей, который не вызывался при заполнении базы данных, поэтому правила проверки, которые я использовал (minlength 4 вместо 6 по умолчанию), не применялись. Убедитесь, что ваш пароль (и все остальные поля в этом отношении) проходят проверку.

Кевин
источник
7
Это помогло мне, так как у меня возникла проблема «UserId not found». Мне удалось отследить его с помощью следующего кода: IdentityResult result = manager.Create(user, "ChangeItAsap!"); if (result.Succeeded == false) { throw new Exception(result.Errors.First()); }
Стив Уилфорд
Этот замечательный комментарий дал мне: «Имя пользователя Demo User недействительно, может содержать только буквы или цифры». вместо того, чтобы просто двусмысленно провалиться с отсутствующим
идентификатором пользователя
Я обнаружил, что мое правило проверки пароля тоже не работает, есть идея?
user1686407 06
15

Это моя основа метода на ответе Валина, я добавил роли в db и добавил пароль для пользователя. Этот код помещается в Seed()метод в Migrations> Configurations.cs.

// role (Const.getRoles() return string[] whit all roles)

    var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
    for (int i = 0; i < Const.getRoles().Length; i++)
    {
        if (RoleManager.RoleExists(Const.getRoles()[i]) == false)
        {
            RoleManager.Create(new IdentityRole(Const.getRoles()[i]));
        }
    }

// user

    var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
    var PasswordHash = new PasswordHasher();
    if (!context.Users.Any(u => u.UserName == "admin@admin.net"))
    {
        var user = new ApplicationUser
        {
             UserName = "admin@admin.net",
             Email = "admin@admin.net",
             PasswordHash = PasswordHash.HashPassword("123456")
         };

         UserManager.Create(user);
         UserManager.AddToRole(user.Id, Const.getRoles()[0]);
    }
Васил Валчев
источник
6

Здесь у меня очень простое, чистое и гладкое решение.

 protected override void Seed(UserContext context)
    { 
        //Step 1 Create the user.
        var passwordHasher = new PasswordHasher();
        var user = new IdentityUser("Administrator");
        user.PasswordHash = passwordHasher.HashPassword("Admin12345");
        user.SecurityStamp = Guid.NewGuid().ToString();

        //Step 2 Create and add the new Role.
        var roleToChoose = new IdentityRole("Admin");
        context.Roles.Add(roleToChoose);

        //Step 3 Create a role for a user
        var role = new IdentityUserRole();
        role.RoleId = roleToChoose.Id;
        role.UserId = user.Id;

         //Step 4 Add the role row and add the user to DB)
        user.Roles.Add(role);
        context.Users.Add(user);
    }
Г-н Тангджай
источник
1
Классная вещь, но ты упустил важную вещь. Вам необходимо добавить user.SecurityStamp = Guid.NewGuid (). ToString (), иначе вы получите ошибку при входе в систему.
eddy white
Спасибо. Я не использовал эту функцию, но добавил ее в свой ответ.
Mr Tangjai
4
protected override void Seed(ApplicationDbContext context)
{
  SeedAsync(context).GetAwaiter().GetResult();
}

private async Task SeedAsync(ApplicationDbContext context)
{
  var userManager = new ApplicationUserManager(new UserStore<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>(context));
  var roleManager = new ApplicationRoleManager(new RoleStore<ApplicationRole, int, ApplicationUserRole>(context));

  if (!roleManager.Roles.Any())
  {
    await roleManager.CreateAsync(new ApplicationRole { Name = ApplicationRole.AdminRoleName });
    await roleManager.CreateAsync(new ApplicationRole { Name = ApplicationRole.AffiliateRoleName });
  }

  if (!userManager.Users.Any(u => u.UserName == "shimmy"))
  {
    var user = new ApplicationUser
    {
      UserName = "shimmy",
      Email = "shimmy@gmail.com",
      EmailConfirmed = true,
      PhoneNumber = "0123456789",
      PhoneNumberConfirmed = true
    };

    await userManager.CreateAsync(user, "****");
    await userManager.AddToRoleAsync(user.Id, ApplicationRole.AdminRoleName);
  }
}
Шимми Вайцхандлер
источник
1
Я настроил свой ApplicationUser для свойства ID с типом int. Ваш подход - единственный, с которым я могу работать с моим индивидуальным пользователем и RoleStores, спасибо!
Майк Девенни
1
Этот бит совершенно неправильно с концептуальной точки зрения: Task.Run(async () => { await SeedAsync(context); }).Wait();. Лучше написать, SeedAsync(context).GetAwait().GetResult();что немного лучше.
Танвир Бадар,
2

Похоже, они меняют способ работы аутентификации в MVC5, изменили мой Global.asax.cs на следующее: помогло!

using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

using System.Threading.Tasks;
using MvcAuth.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using System.Threading;
using Microsoft.AspNet.Identity.EntityFramework;

namespace MvcAuth
{
    public class MvcApplication : System.Web.HttpApplication
    {
        async Task<bool> AddRoleAndUser()
        {
            AuthenticationIdentityManager IdentityManager = new AuthenticationIdentityManager(
                new IdentityStore(new ApplicationDbContext()));

            var role = new Role("Role1");
            IdentityResult result = await IdentityManager.Roles.CreateRoleAsync(role, CancellationToken.None);
            if (result.Success == false)
                return false;

            var user = new ApplicationUser() { UserName = "user1" };
            result = await IdentityManager.Users.CreateLocalUserAsync(user, "Password1");
            if (result.Success == false)
                return false;

            result = await IdentityManager.Roles.AddUserToRoleAsync(user.Id, role.Id, CancellationToken.None);
            return result.Success;
        }

        protected async void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            bool x = await AddRoleAndUser();
        }
    }
}
MrBeanzy
источник
9
Этот ответ больше не актуален, поскольку API-интерфейс ASP.NET Identity изменился.
Джош Маккирин
@ Джош Маккирин У вас есть лучшее решение? поделитесь пожалуйста
Victor.Uduak
2

напишите этот код в своей конфигурации миграции.

Примечание: используйте ApplicationDbContext в классе конфигурации.

    internal sealed class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = false;
    }

    protected override void Seed(ApplicationDbContext context)
    {
        //  This method will be called after migrating to the latest version.

        //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
        //  to avoid creating duplicate seed data.
                   context.Roles.AddOrUpdate(p =>
            p.Id,
                new IdentityRole { Name = "Admins"},
                new IdentityRole { Name = "PowerUsers" },
                new IdentityRole { Name = "Users" },
                new IdentityRole { Name = "Anonymous" }
            );


    }
}
FatalMan
источник