Користувачі та ролі MVC 5


95

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

Моє питання полягає в тому, як розподілити користувачів та ролі? В даний час я засіваю деякі довідкові дані у своєму методі Seed у Configuration.cs. Але мені здається, що таблиці користувачів та ролей не створюються, поки щось вперше не потрапить до AccountController.

На даний момент у мене є два рядки підключення, тому я можу відокремити свої дані від своєї автентифікації в різних базах даних.

Як я можу змусити таблиці користувачів, ролей тощо заповнюватись разом з іншими? А не коли потрапляє контролер облікового запису?


Відповіді:


182

Ось приклад звичайного підходу 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' у консолі менеджера пакетів. Він створить для вас клас конфігурації із методом насіння.
Валін

4
@Zapnologica Migrations настільки проста у використанні. Це також дозволяє редагувати таблиці без повторного створення таблиць. Існує лише три команди, з якими вам потрібно ознайомитись за допомогою консолі NuGet Package Manager. База даних Enable-Migrations, Add-Migration і update-update. Легко пір'ястий.
yardpenalty.com

10
Я буквально скопіював і вставив цей код у свій метод Seed у новій веб-програмі mvc 5, а потім запустив "update-database" у консолі менеджера пакетів. Він додає роль (я бачу її в таблиці AspNetRoles), але коли справа стосується менеджера рядків.AddToRole (user.Id, "AppAdmin"), я отримую повідомлення про помилку "UserId not found." Якщо ви хоч уявляєте, чого я втрачаю, я дуже вдячний цій інформації.
Tom Regan

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!") Не був успішним. Це може мати іншу причину, але для мене це було тому, що мій пароль не зміг підтвердити свою перевірку.

У мене був користувальницький перевірник паролів, який не викликався під час засівання бази даних, тому правила перевірки, до яких я звик (мінімальна довжина 4 замість 6 за замовчуванням), не застосовувалися. Переконайтесь, що ваш пароль (і всі інші поля з цього приводу) проходить перевірку.


7
Це мені допомогло, оскільки у мене виникла проблема "UserId not found". Мені вдалося відстежити його за таким кодом: IdentityResult result = manager.Create(user, "ChangeItAsap!"); if (result.Succeeded == false) { throw new Exception(result.Errors.First()); }
Стів Вілфорд

Цей коментар чудовий, він дав мені "Ім'я користувача Демонстраційний користувач недійсний, може містити лише літери або цифри." замість того, щоб просто неоднозначно
зазнати

Я виявив, що моє правило перевірки пароля теж не працює, будь-яка ідея?
user1686407 06

15

Це моя база методів на відповіді Valin, я додав ролі в db і додав пароль для користувача. Цей код розміщений у Seed()методі в розділі Міграції> Конфігурації.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 (), або ви отримаєте повідомлення про помилку при вході.
вихровий білий

Дякую. Я не користувався цією функцією, але додав її до своєї відповіді.
Містер Тангяй,

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, щоб мати властивість ідентифікованого ідентифікатора 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();
        }
    }
}

9
Ця відповідь більше не актуальна, оскільки API ASP.NET Identity змінився.
Джош Маккерін

@Josh McKearin Чи є у вас краще рішення? поділіться, будь ласка,
Віктор Удуак,

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" }
            );


    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.