JWT身份验证-UserManager.GetUserAsync返回null [英] JWT Authentication - UserManager.GetUserAsync returns 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)
user
是null
.
也许我忘了增加一些额外的要求吗?
Perhaps, I forgot to add some extra claim?
或者也许,一旦我使用JWT,我应该覆盖默认的UserManager
功能,以便它通过保存UserID
的claim
获取用户?
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屋!