JWT身份验证-UserManager.GetUserAsync返回null

时间:2018-07-01 02:18:46

标签: c# asp.net-core asp.net-identity claims-based-identity

AuthController中,进行身份验证时,我创建了一些索赔-UserID是其中之一。

    ...
    Subject = new ClaimsIdentity(new[]
    {
      new Claim(ClaimTypes.Name, user.UserName),
      new Claim("UserID", user.Id.ToString()),
    })

当Angular应用发出请求时,我可以在另一个控制器中获取UserID

Claim claimUserId = User.Claims.SingleOrDefault(c => c.Type == "UserID");

ControllerBase.User实例拥有.Identity对象,而对象又拥有Claims集合。

  • Identity.IsAuthenticated等于True

  • Identity.Name保留admin字符串(相关用户的名称)。

如果我尝试这样获取用户:

var user = await UserManager.GetUserAsync(HttpContext.User)

usernull

也许我忘了增加一些额外的要求吗?

或者也许,一旦我使用JWT,我应该覆盖默认的UserManager功能,以便它通过保存claim的{​​{1}}获取用户?

或者也许有更好的方法?


其他信息:

UserID的注册方式如下

Identity

services.AddIdentity<ApplicationUser, ApplicationRole>() .AddEntityFrameworkStores<AppDbContext>() .AddDefaultTokenProviders(); 字段的类型为ApplicationUser.Id(或在C#中为bigint

此外,我使用long解析的UserManager在EF Seed Data中创建用户

ServiceProvider

1 个答案:

答案 0 :(得分:20)

UserManager.GetUserAsync在内部使用UserManager.GetUserId检索用户的用户ID,然后将其用于从用户存储(即您的数据库)中查询对象。

GetUserId基本上是这样的:

public string GetUserId(ClaimsPrincipal principal)
{
    return principal.FindFirstValue(Options.ClaimsIdentity.UserIdClaimType);
}

因此,这将返回Options.ClaimsIdentity.UserIdClaimType的声明值。 Options是用来配置Identity的IdentityOptions object。默认情况下,UserIdClaimType的值为ClaimTypes.NameIdentifier,即"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"

因此,当您尝试使用该用户主体具有UserManager.GetUserAsync(HttpContext.User)声明的UserID时,用户管理器只是在寻找其他声明。

您可以通过切换到ClaimTypes.NameIdentifier来解决此问题:

new ClaimsIdentity(new[]
{
    new Claim(ClaimTypes.Name, user.UserName),
    new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
})

或者您正确配置了身份,以便它将使用您的UserID声明类型:

// in Startup.ConfigureServices
services.AddIdentity(options => {
    options.ClaimIdentity.UserIdClaimType = "UserID";
});