web-dev-qa-db-fra.com

MVC 5 Seed Utilisateurs et rôles

J'ai joué avec le nouveau MVC 5, j'ai quelques modèles, le contrôleur et la configuration des vues en utilisant les premières migrations de code.

Ma question est: comment puis-je créer des utilisateurs et des rôles? Je sème actuellement des données de référence dans ma méthode Seed dans Configuration.cs. Mais il me semble que les tables des utilisateurs et des rôles ne sont pas créées avant que quelque chose ne se produise pour la première fois dans AccountController.

Je dispose actuellement de deux chaînes de connexion pour pouvoir séparer mes données de mon authentification dans différentes bases de données.

Comment puis-je faire en sorte que l'utilisateur, les rôles, les tables, etc. soient peuplés avec les autres? Et pas quand le contrôleur de compte est touché?

90
MrBeanzy

Voici un exemple d’approche habituelle 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");
    }
}

J'ai utilisé package-manager "update-database". La base de données et toutes les tables ont été créées et ensemencées avec des données.

175
Valin

C'est un petit ajout, mais à quiconque ayant le "UserId not found". message en essayant de semer: (Tom Regan avait cette question dans les commentaires, et j'étais bloquée dessus moi-même pendant un moment)

Cela signifie que le manager.Create (utilisateur, "ChangeItAsap!") N'a pas réussi. Cela peut avoir une raison différente, mais pour moi c'était parce que mon mot de passe ne réussissait pas sa validation.

J'avais un passwordvalidator personnalisé, qui n'était pas appelé lors de l'ensemencement de la base de données; les règles de validation auxquelles j'étais habitué (minlength 4 au lieu de 6 par défaut) ne s'appliquaient pas. Assurez-vous que votre mot de passe (et tous les autres champs) est validé.

15
Kevin

Ceci est ma méthode de base sur la réponse de Valin, j'ai ajouté des rôles dans la base de données et un mot de passe pour l'utilisateur. Ce code est placé dans la méthode Seed() dans 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 == "[email protected]"))
    {
        var user = new ApplicationUser
        {
             UserName = "[email protected]",
             Email = "[email protected]",
             PasswordHash = PasswordHash.HashPassword("123456")
         };

         UserManager.Create(user);
         UserManager.AddToRole(user.Id, Const.getRoles()[0]);
    }
13
Vasil Valchev

Ici, j'ai une solution très facile, propre et lisse.

 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);
    }
5
Mr Tangjai

Ce que je fais est de créer une autre méthode asynchrone et l'appeler de manière synchrone, fonctionne parfaitement pour moi.

protected override void Seed(ApplicationDbContext context)
{
  Task.Run(async () => { await SeedAsync(context); }).Wait();
}

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 = "[email protected]",
      EmailConfirmed = true,
      PhoneNumber = "0123456789",
      PhoneNumberConfirmed = true
    };

    await userManager.CreateAsync(user, "****");
    await userManager.AddToRoleAsync(user.Id, ApplicationRole.AdminRoleName);
  }
}
3
Shimmy

écrivez ce code dans votre configuration de migration.

remarque: utilisez ApplicationDbContext dans la classe de configuration.

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


    }
}
2
FatalMan

On dirait qu'ils changent la façon dont l'authentification fonctionne dans MVC5. Mon Global.asax.cs a été modifié comme suit: l'astuce!

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();
        }
    }
}
2
MrBeanzy