2

In meiner Asp.Net Core-Anwendung möchte ich benutzerdefinierte Ansprüche zu meiner ClaimsIdentity hinzufügen, damit ich auf diese in verschiedenen Schichten meiner Anwendung zugreifen kann. Um dies zu erreichen Ich habe folgenden CodeASP.NET Core 2.0.3 ClaimsTransformer in Kombination mit HttpContextAccessor, Ansprüche werden gelöscht

Startup

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 
     services.AddTransient<IPrincipal>(
      provider => provider.GetService<IHttpContextAccessor>().HttpContext.User); 
     services.AddTransient<IClaimsTransformation, ClaimsTransformer>(); 

ClaimsTransformer

public class ClaimsTransformer : IClaimsTransformation 
{ 
    private readonly IUnitOfWork _unitOfWork; 
    private readonly IPrincipal _principal; 
    public ClaimsTransformer(IUnitOfWork unitOfWork, IPrincipal principal) 
    { 
     _unitOfWork = unitOfWork; 
     _principal = principal; 
    } 
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal) 
    { 
     var currentPrincipal = (ClaimsIdentity)_principal.Identity; 
     var identity = (ClaimsIdentity)principal.Identity; 
     if (currentPrincipal.Claims.All(p => p.Type != "UserId")) 
     { 
      var person = _unitOfWork.PersonRepository.GetPersonBySubjectId(principal.Claims.First(p => p.Type == "sub").Value); 
      person.Wait(); 
      if (person.Result != null) 
      { 
       currentPrincipal.AddClaim(new Claim("UserId", person.Result.Id.ToString())); 
       currentPrincipal.AddClaim(new Claim("TenantId", person.Result.PersonTeams.FirstOrDefault(p => p.Team.TeamType == TeamType.OrganizationTeam)?.Team.OrganizationId.ToString())); 
       if (principal.Claims.Any(p => p.Type == "Admin")) 
       { 
        currentPrincipal.AddClaim(new Claim("Admin", "True")); 
       } 
      } 
      foreach (var claim in identity.Claims) 
      { 
       currentPrincipal.AddClaim(claim); 
      } 
     } 
     return Task.FromResult(principal); 
    } 
} 

Was ich nicht verstehe, ist, wenn ich laufe meine Claimstransformation und ich Schritt durch den Code , alle erforderlichen Ansprüche sind verfügbar, aber wenn ich mein IPrincipal in eine benutzerdefinierte Klasse injiziere, ist die Anspruchsauflistung leer, wenn ich die ClaimsTransformation nicht verwende, die cl Ziele sind über das injizierte IPrincipal verfügbar.

Um dieses Problem zu beheben, füge ich das IPrincipal dem ClaimsTransformer hinzu, dupliziere die Ansprüche aus dem TransformAsync-Eingabeparameter und füge die UserId und TenantId hinzu. Diese funktioniert, aber das Problem, das ich habe ist, dass ich nicht verstehe, warum die Ansprüche gestrichen werden, wenn ich die ClaimsTransformer laufen und warum muss ich hinzufügen, diese hacken

Antwort

1

ich an der gleichen Stelle war. Ich hatte die IPrincipal DI

Startup

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 
services.AddTransient<IClaimsTransformation, ClaimsTransformer>(); 

services.AddAuthentication(IISDefaults.AuthenticationScheme); 

services.AddAuthorization(options => 
     { 
      options.AddPolicy("SystemAdminOnly", policy => policy.RequireClaim(ClaimTypes.Role, "SystemAdmin")); 
     }); 

ClaimsTransformer

public ClaimsTransformer(IRepository repository, IHttpContextAccessor httpContextAccessor/*, IPrincipal principal*/, IMemoryCache cache) 
    { 
     _repository = repository; 
     _httpContextAccessor = httpContextAccessor; 
     // _principal = principal; 
     _cache = cache; 
    } 

public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal) 
    { 
     if (principal.Identity.IsAuthenticated) 
     { 
      var currentPrincipal = (ClaimsIdentity)principal.Identity;//_principal.Identity; 

      var ci = (ClaimsIdentity)principal.Identity; 
      var cacheKey = ci.Name; 

      if (_cache.TryGetValue(cacheKey, out List<Claim> claims)) 
      { 
       currentPrincipal.AddClaims(claims); 
      } 
      else 
      { 
       claims = new List<Claim>(); 
       var isUserSystemAdmin = await _repository.IsUserAdmin(ci.Name); 
       if (isUserSystemAdmin) 
       { 
        var c = new Claim(ClaimTypes.Role, "SystemAdmin"); 
        claims.Add(c); 
       } 

       _cache.Set(cacheKey, claims); 
       currentPrincipal.AddClaims(claims); 
      } 

      //foreach (var claim in ci.Claims) 
      //{ 
      // currentPrincipal.AddClaim(claim); 
      //} 
     } 

     return await Task.FromResult(principal); 
    } 

Und es funktioniert entfernen!

Verwandte Themen