クレームプリンシパルに基づいてIDユーザーを作成する方法[重複]

Nov 24 2020

職場/学校のアカウント認証でasp.netmvcを使用しています。現在、ユーザープロセスにIDを実装しようとしています。

これが私のApplicationUserクラスです:

public class ApplicationUser: IdentityUser
{
    public ICollection<Semester> Semesters { get; set; }
}

これまでのところ、IDは問題なく機能し、問題は1つだけです。学校のアカウントでアプリにログインすると、コントローラーのClaimsPrincipalsようUserに呼び出すことができます。現在取得するにApplicationUserは、使用することができますがUserManagerawait _userManager.GetUserAsync(User)と、UserあることClaimsPrincipals)しかし、私は、データベース内の私の学校のアカウントを格納していないので、結果はnullになります。ApplicationUser次のような新しいものを作成した場合

var newUser = new ApplicationUser()
{
    UserName = User.Identity.Name,
    Email = User.Identity.Name
};
await _userManager.CreateAsync(newUser);
await _userManager.AddClaimsAsync(newUser, User.Claims);

これにより、新しいユーザーが正常に作成され、クレームとともにデータベースに保存されます。しかし、新しいものを作成しようとするApplicationUserawait _userManager.GetUserAsync(User)、結果はnullのままになります。自分にアクセスしてDbContextすべてを取得するApplicationUsersと、新しく作成されたものApplicationUserがそこにあります。では、学校のアカウントログインから取得ApplicationUserしたものClaimsPrincipalsに基づいてを作成するにはどうすればよいですか?

回答

Ogglas Dec 07 2020 at 19:49

このための@pokeへのクレジット。

UserManager.GetUserAsync内部的に使用UserManager.GetUserIdして、ユーザーのユーザーIDを取得します。このIDは、ユーザーストア(つまりデータベース)からオブジェクトをクエリするために使用されます。

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

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

したがって、これはのクレーム値を返しますOptions.ClaimsIdentity.UserIdClaimType。Identityを構成OptionsするIdentityOptionsオブジェクトです。デフォルトでは、の値UserIdClaimTypeClaimTypes.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()),
})

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

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

ソース:

https://stackoverflow.com/a/51122850/3850405

MattE. Dec 04 2020 at 05:55

外部プロバイダーからのクレームは、そのプロバイダーに固有のものになります。アプリのローカルIDストアにログインしているのではなく、ユーザーが誰であるかを知っていると主張しているだけです。したがって、承認に使用する前に、ユーザーをストア(SignInManager)に記録する必要があります。リソースの保護を気にせず、ユーザーを知りたいだけの場合は、内部ストアに直接マップできます

ヘッダー内のクレームは、認証プロバイダーを使用してASPNETの「ミドルウェア」によってインターセプトされる必要があります。ミドルウェアは、ユーザーオブジェクトをHttpContextに設定します。ユーザーを取得したら、ローカルユーザーストアを学校のアカウントのユーザーストアにマッピングし、結果とは別の呼び出しとしてクレームを取得する必要があります。通常、電子メールは件名の主張であり、マッピングに使用できます。

    var userName = User.Identity.Name;
    var user = _userManager.FindByNameAsync(userName);
    var claims = _userManager.GetClaimsAsync(user);