70 votes

Comment remplacer la politique de mot de passe d'ASP.NET Core Identity ?

Par défaut, la politique de mot de passe d'ASP.NET Core Identity exige au moins un caractère spécial, une lettre majuscule, un chiffre, ...

Comment puis-je changer ces restrictions ?

Il n'y a rien à ce sujet dans la documentation ( https://docs.asp.net/en/latest/security/authentication/identity.html )

J'essaie de remplacer le gestionnaire d'utilisateurs de l'identité mais je ne vois pas quelle méthode gère la politique de mot de passe.

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    public ApplicationUserManager(
        DbContextOptions<SecurityDbContext> options,
        IServiceProvider services,
        IHttpContextAccessor contextAccessor,
        ILogger<UserManager<ApplicationUser>> logger)
        : base(
              new UserStore<ApplicationUser>(new SecurityDbContext(contextAccessor)),
              new CustomOptions(),
              new PasswordHasher<ApplicationUser>(),
              new UserValidator<ApplicationUser>[] { new UserValidator<ApplicationUser>() },
              new PasswordValidator[] { new PasswordValidator() },
              new UpperInvariantLookupNormalizer(),
              new IdentityErrorDescriber(),
              services,
              logger
            // , contextAccessor
              )
    {
    }

    public class PasswordValidator : IPasswordValidator<ApplicationUser>
    {
        public Task<IdentityResult> ValidateAsync(UserManager<ApplicationUser> manager, ApplicationUser user, string password)
        {
            return Task.Run(() =>
            {
                if (password.Length >= 4) return IdentityResult.Success;
                else { return IdentityResult.Failed(new IdentityError { Code = "SHORTPASSWORD", Description = "Password too short" }); }
            });
        }
    }

    public class CustomOptions : IOptions<IdentityOptions>
    {
        public IdentityOptions Value { get; private set; }
        public CustomOptions()
        {
            Value = new IdentityOptions
            {
                ClaimsIdentity = new ClaimsIdentityOptions(),
                Cookies = new IdentityCookieOptions(),
                Lockout = new LockoutOptions(),
                Password = null,
                User = new UserOptions(),
                SignIn = new SignInOptions(),
                Tokens = new TokenOptions()
            };
        }
    }
}

J'ajoute cette dépendance du gestionnaire d'utilisateur dans la classe de démarrage :

services.AddScoped<ApplicationUserManager>();

Mais lorsque j'utilise ApplicationUserManager dans les contrôleurs, j'ai l'erreur suivante : Une exception non gérée s'est produite lors du traitement de la requête.

InvalidOperationException : Impossible de résoudre le service de type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[SecurityDbContext]' lors de la tentative d'activation de 'ApplicationUserManager'.

EDIT : La gestion des utilisateurs fonctionne lorsque j'utilise les classes par défaut de l'identité ASP.NET Core, ce n'est donc pas un problème de base de données, ou quelque chose comme ceci

EDIT 2 : J'ai trouvé la solution, il suffit de configurer Identity dans la classe du startup. Ma réponse donne quelques détails.

2 votes

Fait amusant : les valeurs par défaut imposées par MS sont trop strictes pour les mots de passe générés par le gestionnaire de mots de passe chrome.

173voto

AdrienTorris Points 4144

C'est tellement simple en fin de compte...

Il n'est pas nécessaire de surcharger une classe, il suffit de configurer les paramètres d'identité dans votre classe de démarrage, comme ceci :

services.Configure<IdentityOptions>(options =>
{
    options.Password.RequireDigit = false;
    options.Password.RequiredLength = 5;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonLetterOrDigit = true;
    options.Password.RequireUppercase = false;
});

Ou vous pouvez configurer l'identité lorsque vous l'ajoutez :

services.AddIdentity<ApplicationUser, IdentityRole>(options=> {
                options.Password.RequireDigit = false;
                options.Password.RequiredLength = 4;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase = false;
                options.Password.RequireLowercase = false;
            })
                .AddEntityFrameworkStores<SecurityDbContext>()
                .AddDefaultTokenProviders();

AS.NET Core est définitivement une bonne chose ...

4 votes

Solution ajoutée à la documentation officielle docs.asp.net/fr/latest/security/authentication/identity.html

14 votes

En appliquant votre solution, il semble que dans ASP .Net Core l'option options.Password.RequireNonAlphanumeric = false; a été déprécié et divisé en 2 "sous-options" : options.Password.RequireDigit = false; et options.Password.RequireNonAlphanumeric = false; .

0 votes

Intéressant, je voulais autoriser une longueur de mot de passe de 1 au moment du débogage, mais options.Password.RequiredLength = 1 ; n'a pas fonctionné (j'ai essayé les deux scénarios ci-dessus). La validation exigeait toujours 6 caractères. Les autres options ont fonctionné.

7voto

Viacheslav Points 436

Le moyen le plus simple pour les développeurs est

services.AddDefaultIdentity<IdentityUser>(options =>
{
  options.SignIn.RequireConfirmedAccount = true;
  options.Password.RequireDigit = false;
  options.Password.RequireNonAlphanumeric = false;
  options.Password.RequireUppercase = false;
  options.Password.RequireLowercase = false;
})
  .AddEntityFrameworkStores<ApplicationDbContext>();

seulement Password.RequiredLength ne peut pas être changé de cette façon, il est toujours égal à 6.

5voto

Exigence supplémentaire :

Si vous estimez que cette contrainte de mot de passe n'est pas suffisante, Vous pouvez définir vos propres conditions en héritant de la PasswordValidator classe.

Exemple de mise en œuvre :

public class CustomPasswordPolicy : PasswordValidator<AppUser>
    {
        public override async Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user, string password)
        {
            IdentityResult result = await base.ValidateAsync(manager, user, password);
            List<IdentityError> errors = result.Succeeded ? new List<IdentityError>() : result.Errors.ToList();

            if (password.ToLower().Contains(user.UserName.ToLower()))
            {
                errors.Add(new IdentityError
                {
                    Description = "Password cannot contain username"
                });
            }
            if (password.Contains("123"))
            {
                errors.Add(new IdentityError
                {
                    Description = "Password cannot contain 123 numeric sequence"
                });
            }
            return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray());
        }
    }

J'ai surchargé la méthode ValidateAsync dans ma classe, et dans cette méthode, j'implémente ma politique de mot de passe personnalisée.

Très très important

  • La première ligne de code dans ValidateAsync()

IdentityResult result = await base.ValidateAsync(manager, user, password); :

Valide le mot de passe selon les règles de mot de passe données dans la méthode ConfigureServices de la classe Statup (celle montrée dans les anciennes réponses pour ce post)

  • La fonctionnalité de validation du mot de passe est définie par l'interface l'interface IPasswordValidator dans l'espace de noms Microsoft.AspNetCore.Identity. Je dois donc enregistrer ma classe 'CustomPasswordPolicy' comme validateur de mot de passe pour les objets 'AppUser'.

    services.AddTransient<IPasswordValidator<AppUser>, CustomPasswordPolicy>();
            services.AddDbContext<AppIdentityDbContext>(options => options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));
            services.AddIdentity<AppUser, IdentityRole>(opts =>
            {
                opts.Password.RequiredLength = 8;
                opts.Password.RequireNonAlphanumeric = true;
                opts.Password.RequireLowercase = false;
                opts.Password.RequireUppercase = true;
                opts.Password.RequireDigit = true;
            }).AddEntityFrameworkStores<AppIdentityDbContext>().AddDefaultTokenProviders();

Documentation officielle Github de PasswordValidator.cs (pour une meilleure compréhension) : ici

4voto

Vitaly Points 1134

Ajoutez la ligne suivante à la méthode ConfigureServices de startup.cs

services.Configure<IdentityOptions>(Configuration.GetSection(nameof(IdentityOptions)));

Vous pouvez utiliser un nom de section différent si vous le souhaitez

Ajoutez ensuite les paramètres à la configuration. Vous pouvez ajouter plusieurs paramètres dans plusieurs sources de configuration, ils seront fusionnés. Par exemple, je mets ceci dans mon fichier appsettings.local.json. Ce fichier est ignoré par VCS, donc mes paramètres locaux ne sont jamais mis en ligne, contrairement à ce qui se passe si vous codez les paramètres en dur et utilisez #if debug ou quelque chose comme ça.

"IdentityOptions": {
"Password": {
  "RequiredLength": 6,
  "RequireDigit": false,
  "RequiredUniqueChars": 1,
  "RequireLowercase": false,
  "RequireNonAlphanumeric": false,
  "RequireUppercase": false
 }
}

Il en va de même pour appsettings.{Environment}.json ou toute autre source de configuration, de sorte que vous pouvez avoir des paramètres différents sur le serveur de développement et le serveur réel sans modifier le code ou utiliser une configuration de construction différente.

3voto

Shashi Bhat Points 19

Vous pouvez modifier ces règles dans le fichier IdentityConfig.cs. Les règles sont définies dans

 public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
    var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
    // Configure validation logic for usernames
    manager.UserValidator = new UserValidator<ApplicationUser>(manager)
    {
        AllowOnlyAlphanumericUserNames = false,
        RequireUniqueEmail = true
    };

    // Configure validation logic for passwords
    manager.PasswordValidator = new PasswordValidator
    {
        RequiredLength = 5,
        RequireNonLetterOrDigit = false,
        RequireDigit = true,
        RequireLowercase = true,
        RequireUppercase = true,
    };
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X