MVC 5 시드 사용자 및 역할


94

나는 새로운 MVC 5를 가지고 놀았고 코드 우선 마이그레이션을 사용하여 몇 가지 모델, 컨트롤러 및 뷰 설정을 가지고 있습니다.

내 질문은 사용자와 역할을 어떻게 시드합니까? 현재 Configuration.cs의 Seed 메서드에서 일부 참조 데이터를 시드합니다. 그러나 무언가가 AccountController에 처음 도달 할 때까지 사용자 및 역할 테이블이 생성되지 않는 것으로 보입니다.

현재 두 개의 연결 문자열이 있으므로 인증 데이터를 다른 데이터베이스로 분리 할 수 ​​있습니다.

사용자, 역할 등의 테이블을 다른 사람과 함께 채우려면 어떻게해야합니까? 그리고 계정 컨트롤러가 맞을 때가 아니라?


답변:


181

다음은 일반적인 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"를 사용했습니다. DB와 모든 테이블이 생성되고 데이터로 시드되었습니다.


3
Configuration 클래스의 Seed 메서드에. 구성은 enable-migrations의 기본 클래스 이름이지만 변경할 수 있습니다.
Valin

3
패키지 관리자 콘솔에서 'enable-migrations'를 사용해야합니다. 시드 메소드로 구성 클래스를 생성합니다.
Valin 2014.01.28

4
@Zapnologica Migrations는 사용하기 매우 쉽습니다. 또한 테이블을 다시 만들지 않고도 테이블을 편집 할 수 있습니다. NuGet 패키지 관리자 콘솔 사용에 익숙해지는 데 필요한 명령은 세 가지뿐입니다. Enable-Migrations, Add-Migration 및 update-database. 쉬운 피지.
yardpenalty.com 2014 년

10
말 그대로이 코드를 새 mvc 5 웹 응용 프로그램의 Seed 메서드에 복사하여 붙여 넣은 다음 패키지 관리자 콘솔에서 "update-database"를 실행했습니다. 역할을 추가하지만 (AspNetRoles 테이블에서 볼 수 있음), line manager.AddToRole (user.Id, "AppAdmin")에 관해서는 "UserId not found"라는 오류 메시지가 표시됩니다. 내가 무엇을 놓치고 있는지 알고 있다면 정보에 감사드립니다.
Tom Regan 2015

2
context.Users.Add(user);사이에 누락 되었습니다 . 따라서 신생아 사용자에게는 User.Id가 없습니다. manager.Create(user, "ChangeItAsap!");manager.AddToRole(user.Id, "AppAdmin");
ApceH Hypocrite 2017

15

약간의 추가 사항이지만 "UserId를 찾을 수 없음"을 가진 모든 사람에게 적용됩니다. 시드를 시도 할 때 메시지 : (Tom Regan은 댓글에이 질문이 있었는데 저는 잠시 동안이 질문에 매달 렸습니다.)

이것은 manager.Create (사용자, "ChangeItAsap!")가 성공하지 못했음을 의미합니다. 이것은 다른 이유가있을 수 있지만 내 암호가 유효성 검사에 성공하지 못했기 때문입니다.

데이터베이스를 시드 할 때 호출되지 않는 사용자 지정 passwordvalidator가 있었기 때문에 내가 사용했던 유효성 검사 규칙 (기본값 6 대신 minlength 4)이 적용되지 않았습니다. 암호 (및 해당 문제에 대한 다른 모든 필드)가 유효성 검사를 통과하는지 확인하십시오.


7
"사용자 ID를 찾을 수 없음"문제가 발생하여 도움이되었습니다. 나는 다음과 같은 코드로 추적 관리 : IdentityResult result = manager.Create(user, "ChangeItAsap!"); if (result.Succeeded == false) { throw new Exception(result.Errors.First()); }
스티브 윌 포드 우드에게

그 댓글은 훌륭합니다. '사용자 이름 데모 사용자가 유효하지 않습니다. 문자 나 숫자 만 포함 할 수 있습니다.' 대신 누락 된 userId를 함께 모호 실패의
dougajmcdonald

내 암호 확인 규칙도 작동하지 않는다는 것을 알았습니다.
user1686407

15

이것은 Valin 답변에 대한 내 방법 기반이며 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

3
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 유형의 ID 속성을 갖도록 사용자 정의했습니다. 귀하의 접근 방식은 사용자 지정 사용자 및 RoleStores와 함께 작업 할 수있는 유일한 방법입니다. 감사합니다!
Mike Devenney 2017 년

1
이 비트는 개념적 관점에서 완전히 잘못되었습니다 Task.Run(async () => { await SeedAsync(context); }).Wait();.. 차라리 SeedAsync(context).GetAwait().GetResult();약간 더 나은 것을 써야합니다 .
Tanveer Badar

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
이 대답은 ASP.NET Identity API가 변경되었으므로 더 이상 관련이 없습니다.
Josh McKearin 2013 년

@Josh McKearin 더 나은 솔루션이 있습니까? 공유하십시오
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" }
            );


    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.