JWT身份验证-UserManager.GetUserAsync返回null [英] JWT Authentication - UserManager.GetUserAsync returns null

查看:223
本文介绍了JWT身份验证-UserManager.GetUserAsync返回null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In AuthController when authenticating I create a few Claims - UserID is one of them.

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

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

When Angular app makes request I am able to fetch UserID in another controller

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

ControllerBase.User实例包含.Identity对象,该对象又包含Claims集合.

The ControllerBase.User instance holds .Identity object which in turn holds Claims collection.

  • Identity.IsAuthenticated等于True.

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

Identity.Name holds admin string (name of the relevant user).

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

If I try to fetch user like this:

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

usernull.

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

Perhaps, I forgot to add some extra claim?

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

Or maybe, once I'm using JWT - I should override the default UserManager functionality so it fetches user by claim which holds UserID?

或者也许有更好的方法?

Or maybe there's a better approach?


其他信息:

Identity的注册方式如下

services.AddIdentity<ApplicationUser, ApplicationRole>()
    .AddEntityFrameworkStores<AppDbContext>()
    .AddDefaultTokenProviders();

ApplicationUser.Id字段的类型为bigint(或在C#中为long)

ApplicationUser.Id field is of bigint (or in C# of long) type

此外,我在EF Seed Data中使用UserManager创建用户,使用ServiceProvider

Also, I create users in EF Seed Data with UserManager which is resolved using ServiceProvider

_userManager = scope.ServiceProvider.GetService<UserManager<ApplicationUser>>();
    ...
        adminUser.PasswordHash = new PasswordHasher<ApplicationUser>().HashPassword(adminUser, "123qwe");
        _userManager.CreateAsync(adminUser);

推荐答案

UserManager.GetUserId 来检索用户的用户ID,然后该用户ID可用于从用户存储中查询对象(即您的数据库).

UserManager.GetUserAsync internally uses UserManager.GetUserId to retrieve the user id of the user which is then used to query the object from the user store (i.e. your database).

GetUserId基本上是这样的:

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

因此,这将返回Options.ClaimsIdentity.UserIdClaimType的声明值. Options 用于配置身份的对象.默认情况下,UserIdClaimType的值为ClaimTypes.NameIdentifier,即"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier".

So this returns the claim value of Options.ClaimsIdentity.UserIdClaimType. Options is the IdentityOptions object that you configure Identity with. By default the value of UserIdClaimType is ClaimTypes.NameIdentifier, i.e. "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier".

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

So when you try to use UserManager.GetUserAsync(HttpContext.User), where that user principal has a UserID claim, the user manager is simply looking for a different claim.

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

You can fix this by either switchting to the ClaimTypes.NameIdentifier:

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

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

Or you configure Identity properly so it will use your UserID claim type:

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

这篇关于JWT身份验证-UserManager.GetUserAsync返回null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆