ASP.NET Identity UserStore中GetNormalizedUserNameAsync和SetNormalizedUserNameAsync函数的解释

Posted

技术标签:

【中文标题】ASP.NET Identity UserStore中GetNormalizedUserNameAsync和SetNormalizedUserNameAsync函数的解释【英文标题】:Explanation of GetNormalizedUserNameAsync and SetNormalizedUserNameAsync functions in ASP.NET Identity UserStore 【发布时间】:2018-01-02 13:30:00 【问题描述】:

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

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 Sample 和 Actual ASP.NET Core Identity 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);

这些函数是否只是简单地从已填充的用户对象中提取规范化名称并另外更新已填充的用户对象上的规范化名称。我没有看到这些功能的用途,有人可以解释一下吗?

我还需要在我的自定义用户/角色表中实际保留 NormalizedUserName 和 NormalizedRoleName 还是不需要它们?

【问题讨论】:

【参考方案1】:

可以通过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);

目标可能是确保无论输入如何,数据库请求始终使用一致的密钥。

请注意,Identity 框架实际上默认使用UpperInvariantLookupNormalizer(通过IdentityServiceCollectionExtensions.AddIdentity&lt;TUser, TRole&gt;)。

这意味着当你实现IUserStore&lt;User&gt;.FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)时,normalizedUserName不是你传递给UserManager方法的字符串,而是它的大写版本。

所以最后回答你的问题:

GetNormalizedUserNameAsync 不在身份框架的任何地方使用。 SetNormalizedUserNameAsync 在创建/更新用户期间使用,并以您的用户名的大写版本调用。您需要持久化它,但它可能更可取,因为用户查找基于规范化版本。 GetUserNameAsync 在调用 GetNormalizedUserNameAsync 之前将被规范化的字符串。未在身份框架的其他任何地方使用。

最后说明:您可以通过在调用 AddIdentity 之前添加范围服务来更改 ILookupNormalizer

public void ConfigureServices(IServiceCollection services)

    services.AddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
    services
        .AddIdentity<User, Role>()
        .AddUserStore<MyUserStore>()
        .AddRoleStore<MyRoleStore>();

【讨论】:

以上是关于ASP.NET Identity UserStore中GetNormalizedUserNameAsync和SetNormalizedUserNameAsync函数的解释的主要内容,如果未能解决你的问题,请参考以下文章

[ASP.NET MVC] ASP.NET Identity登入技术剖析

ASP.NET Identity系列教程Identity高级技术

ASP.NET MVC Identity 添加角色

ASP.NET Identity系列教程(目录)

ASP.NET Identity系列教程

使用 Identity Server 4 和 ASP.NET Identity 添加外部登录