如何覆盖ASP.NET Core Identity的密码策略

Adr*_*ris 43 c# asp.net-identity asp.net-core-mvc asp.net-core-identity

默认情况下,ASP.NET Core Identity的密码策略至少需要一个特殊字符,一个大写字母,一个数字,......

我该如何更改此限制?

文档中没有任何内容(https://docs.asp.net/en/latest/security/authentication/identity.html)

我尝试覆盖Identity的用户管理器,但我没有看到哪个方法管理密码策略.

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()
            };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在启动的类中添加了这个用户管理器依赖项:

services.AddScoped<ApplicationUserManager>();
Run Code Online (Sandbox Code Playgroud)

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

InvalidOperationException:尝试激活'ApplicationUserManager'时,无法解析类型'Microsoft.EntityFrameworkCore.DbContextOptions`1 [SecurityDbContext]'的服务.

编辑:当我使用ASP.NET核心标识的默认类时,用户的管理工作,所以它不是数据库问题,或类似的东西

编辑2:我找到了解决方案,你只需要在启动类中配置Identity.我的回答提供了一些细节.

Adr*_*ris 114

最后它太简单了......

无需覆盖任何类,您只需在启动类中配置身份设置,如下所示:

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

或者您可以在添加时配置身份:

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();
Run Code Online (Sandbox Code Playgroud)

AS.NET Core绝对是好东西......

  • 应用您的解决方案,它看起来像ASP .Net Core中的选项`options.Password.RequireNonAlphanumeric = false;`已被弃用并分为2个"子选项":`options.Password.RequireDigit = false;`和`options .Password.RequireNonAlphanumeric = false;`. (11认同)
  • 解决方案已添加到官方文档https://docs.asp.net/en/latest/security/authentication/identity.html (3认同)

Via*_*lav 9

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

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>();
Run Code Online (Sandbox Code Playgroud)

只有Password.RequiredLength不能以这种方式更改,它仍然等于6。


Shr*_*gam 8

附加要求:

\n\n
\n

如果您觉得这个密码约束还不够,您可以通过继承PasswordValidator 来定义您自己的条件。

\n
\n\n

示例实现:

\n\n
public class CustomPasswordPolicy : PasswordValidator<AppUser>\n    {\n        public override async Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user, string password)\n        {\n            IdentityResult result = await base.ValidateAsync(manager, user, password);\n            List<IdentityError> errors = result.Succeeded ? new List<IdentityError>() : result.Errors.ToList();\n\n            if (password.ToLower().Contains(user.UserName.ToLower()))\n            {\n                errors.Add(new IdentityError\n                {\n                    Description = "Password cannot contain username"\n                });\n            }\n            if (password.Contains("123"))\n            {\n                errors.Add(new IdentityError\n                {\n                    Description = "Password cannot contain 123 numeric sequence"\n                });\n            }\n            return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray());\n        }\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

非常非常重要

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

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

\n\n

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

\n\n
    \n
  • 密码验证功能由 Microsoft.AspNetCore.Identity 命名空间中的\nIPasswordValidator 接口定义。因此,我需要将 \xe2\x80\x98CustomPasswordPolicy\xe2\x80\x99 类注册为 \xe2\x80\x98AppUser\xe2\x80\x99 对象的密码验证器。
  • \n
\n\n
    services.AddTransient<IPasswordValidator<AppUser>, CustomPasswordPolicy>();\n            services.AddDbContext<AppIdentityDbContext>(options => options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));\n            services.AddIdentity<AppUser, IdentityRole>(opts =>\n            {\n                opts.Password.RequiredLength = 8;\n                opts.Password.RequireNonAlphanumeric = true;\n                opts.Password.RequireLowercase = false;\n                opts.Password.RequireUppercase = true;\n                opts.Password.RequireDigit = true;\n            }).AddEntityFrameworkStores<AppIdentityDbContext>().AddDefaultTokenProviders();\n\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

PasswordValidator.cs的官方 Github 文档(为了更好\n 理解):此处

\n
\n


Vit*_*aly 6

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

services.Configure<IdentityOptions>(Configuration.GetSection(nameof(IdentityOptions)));
Run Code Online (Sandbox Code Playgroud)

如果需要,您可以使用不同的部分名称

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

"IdentityOptions": {
"Password": {
  "RequiredLength": 6,
  "RequireDigit": false,
  "RequiredUniqueChars": 1,
  "RequireLowercase": false,
  "RequireNonAlphanumeric": false,
  "RequireUppercase": false
 }
}
Run Code Online (Sandbox Code Playgroud)

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