我对如何实现以下功能感到困惑:
GetNormalizedRoleNameAsync(TRole, CancellationToken)
SetNormalizedRoleNameAsync(TRole, String, CancellationToken)
GetNormalizedUserNameAsync(TUser, CancellationToken)
SetNormalizedUserNameAsync(TUser, String, CancellationToken)
GetUserNameAsync(TUser, CancellationToken)
SetUserNameAsync(TUser, String, CancellationToken)
在ASP.NET Core CustomIdentityProvider示例和实际ASP.NET核心标识UserStoreBase类中,它们执行以下操作:
public Task SetNormalizedUserNameAsync(ApplicationUser user, string normalizedName, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (user == null) throw new ArgumentNullException(nameof(user));
if (normalizedName == null) throw new ArgumentNullException(nameof(normalizedName));
user.NormalizedUserName = normalizedName;
return Task.FromResult<object>(null);
}
public Task<string> GetUserNameAsync(ApplicationUser user, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (user == null) throw new ArgumentNullException(nameof(user));
return Task.FromResult(user.UserName);
}
这些函数是仅仅从已填充的User对象中提取Normalized Name,还是在已填充的User对象上更新Normalized Name。我没有看到这些功能的目的可以解释一下吗?
我是否还需要在自定义用户/角色表中实际保留NormalizedUserName和NormalizedRoleName,还是不需要?
答案 0 :(得分:3)
可以通过UserManager
和RoleManager
查找用户/角色的方式找到答案。由于它们的工作原理相似,因此我将重点介绍UserManager
。
调用UserManager.FindByNameAsync
时,UserManager
首先将密钥标准化,然后再将其传递给UserStore
:
public virtual async Task<TUser> FindByNameAsync(string userName)
{
userName = NormalizeKey(userName);
var user = await Store.FindByNameAsync(userName, CancellationToken);
return user;
}
其中
// injected via dependency injection
ILookupNormalizer keyNormalizer;
public virtual string NormalizeKey(string key)
{
return (KeyNormalizer == null) ? key : KeyNormalizer.Normalize(key);
}
目标可能是确保无论输入如何,DB请求始终使用一致的密钥。
请注意,默认情况下,Identity框架实际上使用UpperInvariantLookupNormalizer
(通过IdentityServiceCollectionExtensions.AddIdentity<TUser, TRole>
)。
这意味着在实现IUserStore<User>.FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
时,normalizedUserName
不是传递给UserManager
方法的字符串,而是它的大写版本。
因此,最后回答您的问题:
GetNormalizedUserNameAsync
在Identity框架的任何地方都没有使用。SetNormalizedUserNameAsync
在创建/更新用户时使用,并以用户名的大写形式调用。您不需要 保留它,但这可能是更可取的,因为User查找基于规范化版本。GetUserNameAsync
在调用GetNormalizedUserNameAsync
之前将被规范化的字符串。不在Identity框架中的其他任何地方使用。最后的提示:您可以在调用ILookupNormalizer
之前通过添加范围服务来更改AddIdentity
:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
services
.AddIdentity<User, Role>()
.AddUserStore<MyUserStore>()
.AddRoleStore<MyRoleStore>();
}