web-dev-qa-db-fra.com

Implémentation d'une revendication personnalisée avec un utilisateur MVC Core Identity étendu

Comment puis-je créer une revendication d'autorisation personnalisée dans MVC Core 2.0 (en utilisant AspNetCore.identity) pour vérifier une propriété booléenne utilisateur personnalisée? J'ai étendu l'IdentityUser (ApplicationUser) pour inclure une valeur booléenne "IsDeveloper". J'utilise l'authentification basée sur les revendications et je voudrais ajouter une revendication personnalisée, mais je ne sais pas par où commencer. Comment puis-je créer une revendication personnalisée qui:

  1. Recherchez l'utilisateur actuel (personnalisé) de Core.Identity.
  2. Évaluer la valeur booléenne d'un utilisateur d'identité personnalisé?

Je comprends les revendications d'identité de base MSDN: Authentification basée sur les revendications , mais je suis nouveau dans les revendications personnalisées, donc je ne sais pas par où commencer. Les documents en ligne que j'ai trouvés ne fonctionnent pas ou ne correspondent pas à mon scénario.

10
davewilliams459

Vous devez donc créer quelque part des revendications personnalisées, puis les vérifier via une stratégie personnalisée ou manuellement.

1) Ajout de revendications personnalisées

Authentification JwtBearer

Vous pouvez faire quelque chose comme ça:

Dans votre action de contrôleur qui renvoie jwt-token, vous pouvez ajouter votre custom claim:

[HttpGet]
public dynamic GetToken(string login, string password)
{
    var handler = new JwtSecurityTokenHandler();

    var sec = "12312313212312313213213123123132123123132132132131231313212313232131231231313212313213132123131321313213213131231231213213131311";
    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(sec));
    var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);

    var user = GetUserFromDb(login);
    var identity = new ClaimsIdentity(new GenericIdentity(user.Email), new[] { new Claim("user_id", user.Id) });
    if (user.IsDeveloper)
        identity.AddClaim(new Claim("IsDeveloper", "true"));
    var token = handler.CreateJwtSecurityToken(subject: identity,
                                                signingCredentials: signingCredentials,
                                                audience: "ExampleAudience",
                                                issuer: "ExampleIssuer",
                                                expires: DateTime.UtcNow.AddSeconds(100));
    return handler.WriteToken(token);
}

Authentification d'identité ASP.NET Core

Vous devez implémenter un IUserClaimsPrincipalFactory personnalisé ou utiliser UserClaimsPrincipalFactory comme classe de base:

public class ApplicationClaimsIdentityFactory: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory <ApplicationUser>
{
    UserManager<ApplicationUser> _userManager;
    public ApplicationClaimsIdentityFactory(UserManager<ApplicationUser> userManager, 
        IOptions<IdentityOptions> optionsAccessor):base(userManager, optionsAccessor)
    {}
    public async override Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
    {
        var principal = await base.CreateAsync(user);
        if (user.IsDeveloper)
        {
            ((ClaimsIdentity)principal.Identity).AddClaims(new[] {
                new Claim("IsDeveloper", "true")
            });
        }
        return principal;
    }
}

alors vous devez l'enregistrer dans Startup.ConfigureServices:

services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, ApplicationClaimsIdentityFactory>();

2) Vérifiez la réclamation

Politique personnalisée

Dans Startup.ConfigureServices:

services.AddAuthorization(options =>
{
    options.AddPolicy("Developer", policy =>
                        policy.RequireClaim("IsDeveloper", "true"));
});

et protégez votre action pour les développeurs:

[Authorize(Policy = "Developer"), HttpGet]
public string DeveloperSecret()
{
    return "Hello Developer"
}

Vérifier la réclamation manuellement

Quelque part dans le contrôleur:

bool isDeveloper = User.Claims.Any(c => c.Type == "IsDeveloper" && c.Value == "true")

Si vous utilisez une autre authentification, l'idée devrait être la même.

20
AlbertK