ผู้ใช้เมล็ดพันธุ์ MVC 5 และบทบาท


95

ฉันเล่นกับ MVC 5 ใหม่ฉันมีโมเดลตัวควบคุมและการตั้งค่ามุมมองบางอย่างโดยใช้การย้ายรหัสครั้งแรก

คำถามของฉันคือฉันจะสร้างผู้ใช้และบทบาทได้อย่างไร ขณะนี้ฉันเพาะข้อมูลอ้างอิงบางส่วนในเมธอด Seed ของฉันใน Configuration.cs แต่สำหรับฉันแล้วดูเหมือนว่าตารางผู้ใช้และบทบาทจะไม่ถูกสร้างขึ้นจนกว่าจะมีสิ่งแรกกระทบ AccountController

ขณะนี้ฉันมีสตริงการเชื่อมต่อสองสายดังนั้นฉันจึงสามารถแยกข้อมูลจากการพิสูจน์ตัวตนไปยังฐานข้อมูลอื่นได้

ฉันจะทำให้ตารางผู้ใช้บทบาทและอื่น ๆ พร้อมกับตารางอื่น ๆ ของฉันได้อย่างไร และไม่ใช่เมื่อตัวควบคุมบัญชีถูกโจมตี?


คำตอบ:


183

นี่คือตัวอย่างของแนวทางการเพาะเมล็ดตามปกติ:

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

ฉันใช้ package-manager "update-database" ฐานข้อมูลและตารางทั้งหมดถูกสร้างขึ้นและมีข้อมูล


3
ไปยังเมธอด Seed ของคลาส Configuration Configuration คือชื่อคลาสเริ่มต้นสำหรับ enable-migrations แต่คุณสามารถเปลี่ยนได้
Valin

3
คุณควรใช้ 'enable-migrations' ในคอนโซลตัวจัดการแพ็คเกจ มันจะสร้างคลาสคอนฟิกูเรชันด้วยเมธอด seed ให้คุณ
Valin

4
@Zapnologica Migrations ใช้งานง่ายมาก นอกจากนี้ยังช่วยให้คุณสามารถแก้ไขตารางของคุณโดยไม่ต้องสร้างตารางขึ้นมาใหม่ มีเพียงสามคำสั่งที่คุณต้องทำความคุ้นเคยโดยใช้ NuGet Package Manager Console เปิดใช้งานการโยกย้ายเพิ่มการโยกย้ายและการปรับปรุงฐานข้อมูล ขี้เกียจง่าย
yardpenalty.com

10
ฉันคัดลอกและวางโค้ดนี้ลงในเมธอด Seed ของฉันในเว็บแอปพลิเคชัน mvc 5 ใหม่จากนั้นเรียกใช้ "update-database" ในคอนโซลตัวจัดการแพ็กเกจ มันเพิ่มบทบาท (ฉันเห็นได้ในตาราง AspNetRoles) แต่เมื่อพูดถึงตัวจัดการสาย AddToRole (user.Id, "AppAdmin") ฉันได้รับข้อความแสดงข้อผิดพลาด "ไม่พบ UserId" หากคุณมีความคิดว่าฉันขาดอะไรไปฉันขอขอบคุณข้อมูลนี้มาก
Tom Regan

2
พลาดcontext.Users.Add(user);ระหว่างและmanager.Create(user, "ChangeItAsap!"); manager.AddToRole(user.Id, "AppAdmin");ผู้ใช้แรกเกิดจึงไม่มี User.Id.
ApceH Hypocrite

15

เป็นส่วนเพิ่มเติมเล็กน้อย แต่สำหรับทุกคนที่มี "ไม่พบ UserId" ข้อความเมื่อพยายามเพาะเมล็ด: (Tom Regan มีคำถามนี้ในความคิดเห็นและฉันก็ติดอยู่กับมันอยู่พักหนึ่ง)

ซึ่งหมายความว่า manager.Create (ผู้ใช้ "ChangeItAsap!") ไม่สำเร็จ ซึ่งอาจมีเหตุผลอื่น แต่สำหรับฉันแล้วเป็นเพราะรหัสผ่านของฉันไม่ผ่านการตรวจสอบความถูกต้อง

ฉันมีตัวตรวจสอบรหัสผ่านที่กำหนดเองซึ่งไม่ได้ถูกเรียกเมื่อเริ่มต้นฐานข้อมูลดังนั้นจึงใช้กฎการตรวจสอบความถูกต้องที่ฉันใช้ (minlength 4 แทนค่าเริ่มต้น 6) ไม่ได้ ตรวจสอบให้แน่ใจว่ารหัสผ่านของคุณ (และช่องอื่น ๆ ทั้งหมดสำหรับกรณีนั้น) กำลังผ่านการตรวจสอบความถูกต้อง


7
สิ่งนี้ช่วยฉันได้เนื่องจากฉันมีปัญหา "ไม่พบ UserId" ฉันสามารถติดตามมันได้ด้วยรหัสต่อไปนี้: IdentityResult result = manager.Create(user, "ChangeItAsap!"); if (result.Succeeded == false) { throw new Exception(result.Errors.First()); }
Steve Wilford

ความคิดเห็นนั้นยอดเยี่ยมมากทำให้ฉัน 'ชื่อผู้ใช้สาธิตผู้ใช้ไม่ถูกต้องสามารถมีได้เฉพาะตัวอักษรหรือตัวเลขเท่านั้น' แทนที่จะล้มเหลวอย่างคลุมเครือกับ userId ที่หายไป
dougajmcdonald

ฉันพบว่ากฎการตรวจสอบรหัสผ่านของฉันใช้ไม่ได้เช่นกันมีความคิดอย่างไร
user1686407

15

นี่คือวิธีการของฉันตามคำตอบ Valin ฉันได้เพิ่มบทบาทในฐานข้อมูลและเพิ่มรหัสผ่านสำหรับผู้ใช้ รหัสนี้อยู่ในSeed()method ใน 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

ขอบคุณ. ฉันไม่ได้ใช้คุณสมบัตินั้น แต่ฉันได้เพิ่มมันเข้าไปในคำตอบของฉัน
นายตั้งใจ

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 แนวทางของคุณเป็นแนวทางเดียวที่ฉันจะได้ใช้กับ User และ RoleStores แบบกำหนดเองของฉันขอบคุณ!
Mike Devenney

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

@ Josh McKearin คุณมีทางออกที่ดีกว่านี้ไหม? โปรดแบ่งปัน
Victor.Uduak

2

เขียนรหัสนี้ในการกำหนดค่าการย้ายข้อมูลของคุณ

หมายเหตุ: ใช้ ApplicationDbContext ใน Configuration Class

    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.