如何重写ASP.. NET Core Identity's密码策略

本文关键字:Identity 策略 密码 Core NET 何重写 重写 ASP | 更新日期: 2023-09-27 18:09:53

. NET Core Identity的密码策略至少需要一个特殊字符,一个大写字母,一个数字,…

如何更改此限制?

文档中没有这方面的内容(https://docs.asp.net/en/latest/security/authentication/identity.html)

我尝试覆盖身份的用户管理器,但我不知道哪个方法管理密码策略。

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

我在startup的类中添加了这个user manager依赖:

services.AddScoped<ApplicationUserManager>();

但是当我在控制器中使用ApplicationUserManager时,我有错误:处理请求时发生未处理的异常。

InvalidOperationException:无法解析类型为"Microsoft.EntityFrameworkCore"的服务。当试图激活'ApplicationUserManager'时,DbContextOptions ' 1[SecurityDbContext] .

EDIT:当我使用ASP时,用户的管理工作。. NET Core Identity的默认类,所以这不是数据库问题,或类似的东西

如何重写ASP.. NET Core Identity's密码策略

最后它是如此的简单…

不需要重写任何类,你只需要在你的启动类中配置标识设置,像这样:

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

或者您可以在添加时配置标识:

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();

。. NET Core绝对是好东西…

对于开发人员来说最简单的方法是

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>();

只有密码。6.

附加要求:

如果您觉得这个密码约束还不够,您可以定义您的类来拥有条件 PasswordValidator

示例实现:

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

我已经在我的类中重写了ValidateAsync方法,并且在这个方法中我实现了我的自定义密码策略

非常非常重要

  • ValidateAsync()
  • 中的第一行代码

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

根据在Statup类的ConfigureServices方法中给出的密码规则验证密码(在这篇文章的旧答案中显示)

  • 密码验证功能由在Microsoft.AspNetCore.Identity命名空间中的IPasswordValidator接口。所以我需要注册我的' CustomPasswordPolicy '类作为' 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();

官方Github文档PasswordValidator.cs(更好这里理解):

将以下行添加到startup.cs的ConfigureServices方法

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

如果需要,可以使用不同的section名

然后在config中添加设置。您可以在多个配置源中添加多个设置,它们将被合并。我把它放在appsettings.local.json文件中。这个文件被VCS忽略,因此我的本地设置永远不会生效,不像你硬编码设置并使用#if debug或类似的东西。

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

同样适用于appsettings.{Environment}。Json或任何其他配置源,因此您可以在开发服务器和活动服务器上有不同的设置,而无需更改代码或使用不同的构建配置

您可以在IdentityConfig.cs文件中修改这些规则。规则在

中定义
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,
    };
}

我提出这样的解决方案:

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

这是基于这个函数validate将运行2次的事实。
第一次为PasswordValidator,第二次在CustomPasswordPolicy中再次运行。