2

私のAsp.Net Coreアプリケーションでは、私のClaimsIdentityにカスタムクレームを追加したいので、アプリケーションのさまざまなレイヤーでこれらのレイヤーにアクセスできます。私は私のClaimstransformationを実行し、私はコードをステップするとき、私は理解していないどのような次のコードASP.NET Core 2.0.3 ClaimsTransformerとHttpContextAccessorを組み合わせて、クレームをクリアしています

スタートアップ

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); 
    } 
} 

を追加し、これを達成するために、ありますすべての必要なクレームは利用可能ですが、自分のIPrincipalをカスタムクラスに注入すると、ClaimsTransformationを使用しない場合、クレームコレクションは空です目的は注入されたIPrincipalを介して利用可能です。

この問題を解決するために、自分のIPrincipalをClaimsTransformerに追加し、TransformAsync入力パラメーターから要求を複製し、UserIdとTenantIdを追加します。 これは動作しますが、私が持っている問題は、私はClaimsTransformerを実行するとクレームが削除されている理由と私は同じ場所にあったこのハック

答えて

1

を追加する必要がある理由私は理解していないということです。 私は

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); 
    } 

ClaimsTransformer

スタートアップ

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

services.AddAuthentication(IISDefaults.AuthenticationScheme); 

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

IPrincipal DIを削除する必要がありましたそして、それは働きます!

関連する問題