Comment créer un utilisateur d'identité basé sur les revendications prinicpals [duplicate]

Nov 24 2020

J'utilise asp.net mvc avec l'authentification des comptes professionnels / scolaires. Actuellement, j'essaie d'implémenter l'identité dans le processus utilisateur.

Voici ma ApplicationUserclasse:

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

Jusqu'à présent, l'identité fonctionne très bien, il n'y a qu'un seul problème. Lorsque je me connecte à l'application avec mon compte scolaire, je peux appeler le ClaimsPrincipalscomme Userdans les contrôleurs. Pour obtenir le courant, ApplicationUservous pouvez utiliser le UserManager( await _userManager.GetUserAsync(User), en Userétant le ClaimsPrincipals) Mais comme je n'ai pas stocké mon compte scolaire dans la base de données, le résultat sera nul. Si je crée un nouveau ApplicationUsercomme le suivant

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

Cela créera et enregistrera avec succès le nouvel utilisateur dans la base de données avec les revendications. Mais alors quand j'essaye d'obtenir le nouveau créé ApplicationUseravec await _userManager.GetUserAsync(User)le résultat sera toujours nul. Si j'accède à my DbContextet que j'obtiens tout ApplicationUsers, le nouvellement créé ApplicationUserest là. Alors, comment puis-je créer un en ApplicationUserfonction de la ClaimsPrincipalsconnexion que j'obtiens à mon compte scolaire?

Réponses

Ogglas Dec 07 2020 at 19:49

Crédits à @poke pour cela.

UserManager.GetUserAsyncutilise en interne UserManager.GetUserIdpour récupérer l'ID utilisateur de l'utilisateur qui est ensuite utilisé pour interroger l'objet à partir du magasin d'utilisateurs (c'est-à-dire votre base de données).

GetUserId ressemble essentiellement à ceci:

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

Cela renvoie donc la valeur de réclamation de Options.ClaimsIdentity.UserIdClaimType. Optionsest l' IdentityOptionsobjet avec lequel vous configurez Identity. Par défaut, la valeur de UserIdClaimTypeest ClaimTypes.NameIdentifier, ie "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier".

Ainsi, lorsque vous essayez d'utiliser UserManager.GetUserAsync(HttpContext.User), lorsque ce principal utilisateur a une UserIDrevendication, le gestionnaire d'utilisateurs recherche simplement une revendication différente.

Vous pouvez résoudre ce problème en passant à ClaimTypes.NameIdentifier:

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

Ou vous configurez correctement Identity afin qu'il utilise votre UserIDtype de revendication:

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

La source:

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

MattE. Dec 04 2020 at 05:55

Les réclamations d'un fournisseur externe seront spécifiques à ce fournisseur. Il ne se connecte pas au magasin d'identités local dans votre application, il prétend simplement savoir qui est l'utilisateur. Vous devez donc connecter l'utilisateur à votre boutique (SignInManager) avant de pouvoir l'utiliser pour l'autorisation. Si vous ne vous souciez pas de la protection des ressources et que vous souhaitez simplement connaître l'utilisateur, vous pouvez directement mapper à votre magasin interne

Les revendications dans l'en-tête doivent être interceptées par le «middleware» ASPNET à l'aide d'un fournisseur d'authentification qui définira ensuite l'objet User dans HttpContext. Une fois que vous avez l'utilisateur, vous devez mapper votre magasin d'utilisateurs local avec ceux du compte de l'école, puis obtenir les revendications en tant qu'appel distinct du résultat. Habituellement, l'e-mail est le sujet de la revendication et peut être utilisé pour le mappage:

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