学习目录
为什么会有配置
正常情况下,任何一个产品使用的用户,都会根据自身的业务要求做一些定制化的功能,比如有些想要对用户名做限制,有些需要在密码做限制等等,那软件开发商需要提取这些功能配置的需求,然后做成系统可配置管理,这样就可以将这个个性化需求又用户自行配置和管理。
Identity 也可以配置吗?
答案是肯定的。但 Microsoft.AspNetCore.Identity
是一个框架,它面向的是开发人员,而不是终端普通用户,所以它的配置需要通过代码实现。
打开 Startup.cs
这个类,我们来进行一些配置。
使用 AddDefaultIdentity
的第二个重载进行配置。
配置用户名
services.AddDefaultIdentity<IdentityUser>(options=>
{
options.User = new UserOptions
{
RequireUniqueEmail = true, //要求Email唯一
AllowedUserNameCharacters = "abcdefgABCDEFG" //允许的用户名字符,默认是 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+
};
})
可惜这玩意儿不支持正则表达式,如果你让用户名支持中文的话…这得写多少汉字进去…
配置密码
services.AddDefaultIdentity<IdentityUser>(options=>
{
options.Password = new PasswordOptions
{
RequiredLength = 8, //要求密码最小长度,默认是 6 个字符
RequireDigit = true, //要求有数字
RequiredUniqueChars = 3, //要求至少要出现的字母数
RequireLowercase = true, //要求小写字母
RequireNonAlphanumeric = true, //要求特殊字符
RequireUppercase = true //要求大写字母
};
})
锁定账户
services.AddDefaultIdentity<IdentityUser>(options=>
{
options.Lockout = new LockoutOptions
{
AllowedForNewUsers = true, // 新用户锁定账户
DefaultLockoutTimeSpan = TimeSpan.FromHours(1), //锁定时长,默认是 5 分钟
MaxFailedAccessAttempts = 3 //登录错误最大尝试次数,默认 5 次
};
})
数据库存储
services.AddDefaultIdentity<IdentityUser>(options=>
{
options.Stores = new StoreOptions
{
MaxLengthForKeys = 128, // 主键的最大长度
ProtectPersonalData = true //保护用户数据,要求实现 IProtectedUserStore 接口
};
})
如果不设置,主键则是 max 的字符串长度。
令牌配置
services.AddDefaultIdentity<IdentityUser>(options=>
{
options.Tokens = new TokenOptions
{
AuthenticatorIssuer = "Identity", //认证的消费者
AuthenticatorTokenProvider = "MyAuthenticatorTokenProvider", //认证令牌的提供者
ChangeEmailTokenProvider = "MyChangeEmailTokenProvider", //更换邮箱的令牌提供者
ChangePhoneNumberTokenProvider = "MyChangePhoneNumberTokenProvider", //更换手机号的令牌提供者
EmailConfirmationTokenProvider = "MyEmailConfirmationTokenProvider", //验证邮箱的令牌提供者
PasswordResetTokenProvider = "MyPasswordResetTokenProvider", //重置密码的令牌提供者
ProviderMap = new Dictionary<string, TokenProviderDescriptor>()
};
})
这部分是二次开发使用的,这些所谓的 TokenProvider
可以自定义,比如如何生成令牌,然后用什么方式将令牌发给用户,请求用户验证。
手机验证码这个场景应该都不陌生了吧。那在框架中,你不可能直接去写发送验证码的代码,而是通过继承某个接口,然后在程序入口的地方更换这个接口的实例,这样框架内部在遇到该接口时,就会使用你的实例,去发送手机验证码。
声明配置
services.AddDefaultIdentity<IdentityUser>(options=>
{
options.ClaimsIdentity = new ClaimsIdentityOptions
{
RoleClaimType = "IdentityRole",
UserIdClaimType = "IdentityId",
SecurityStampClaimType = "SecurityStamp",
UserNameClaimType = "IdentityName"
};
})
如果你还是在使用基于角色的授权方式,可以学习基于声明的授权,而现在却有一种更高级的方式:基于策略的授权。
登录认证配置
services.AddDefaultIdentity<IdentityUser>(options=>
{
options.SignIn = new SignInOptions
{
RequireConfirmedEmail = true, //要求激活邮箱
RequireConfirmedPhoneNumber = true //要求激活手机号
};
})
在登录的时候,如果手机号或邮箱没有激活/确认,则无法登录。
总结
以上都是使用硬编码的方式来进行配置,当然你可以通过从数据库中读取配置,然后反序列化给该对象,这样你就只需要进行配置文件的修改即可达到目的,但这样的配置是在注入时完成的,所以你还需要更新注入的实例,这就需要花一些技术手段了。