web-dev-qa-db-ja.com

JWT認証-UserManager.GetUserAsyncがnullを返す

認証時にAuthControllerをいくつか作成しますClaims-UserIDはその1つです。

...
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.IsAuthenticatedTrueと同じです。

  • Identity.Nameadmin文字列(関連するユーザーの名前)を保持します。

このようにユーザーをフェッチしようとすると:

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

usernullです。

おそらく、追加のクレームを追加するのを忘れましたか?

あるいは、JWTを使用したら、デフォルトのUserManager機能をオーバーライドして、claimを保持するUserIDによってユーザーをフェッチする必要がありますか?

それとももっと良いアプローチがありますか?


追加情報:

Identityは次のように登録されています

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

ApplicationUser.Idフィールドはbigint(またはC#ではlong)タイプです

また、ServiceProviderを使用して解決されるUserManagerでEF Seed Dataにユーザーを作成します

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

_UserManager.GetUserAsync_ 内部で _UserManager.GetUserId_ を使用して、ユーザーのユーザーIDを取得します。これを使用して、ユーザーストア(つまり、データベース)からオブジェクトをクエリします)。

GetUserIdは基本的に次のようになります:

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

したがって、これは_Options.ClaimsIdentity.UserIdClaimType_のクレーム値を返します。 Optionsは、Identityを構成する IdentityOptionsオブジェクト です。デフォルトでは、UserIdClaimTypeの値は_ClaimTypes.NameIdentifier_、つまり_"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"_です。

そのため、ユーザープリンシパルがUserIDクレームを持つUserManager.GetUserAsync(HttpContext.User)を使用しようとすると、ユーザーマネージャーは単に別のクレームを探しています。

_ClaimTypes.NameIdentifier_に切り替えることで、これを修正できます。

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

または、Identityを適切に構成して、UserIDクレームタイプを使用するようにします。

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