ASP.NET Identity UserStore中的GetNormalizedUserNameAsync和SetNormalizedUserNameAsync函数的说明

时间:2017-07-27 02:20:03

标签: c# asp.net asp.net-mvc asp.net-core asp.net-identity

我对如何实现以下功能感到困惑:

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,还是不需要?

1 个答案:

答案 0 :(得分:3)

可以通过UserManagerRoleManager查找用户/角色的方式找到答案。由于它们的工作原理相似,因此我将重点介绍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>();
}