2

내 Asp.Net 핵심 응용 프로그램에서 내 응용 프로그램의 서로 다른 계층에서 이들을 액세스 할 수 있도록 사용자 지정 클레임을 내 ClaimsIdentity에 추가하려고합니다. 내가 코드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); 
    } 
} 

이해가 안 무엇입니까, 내 Claimstransformation를 실행하고 나는 코드를 단계별로 때 모든 필요한 클레임을 사용할 수 있지만 사용자 정의 클래스에 IPrincipal을 삽입하면 ClaimsTransformation을 사용하지 않으면 클레임 컬렉션이 비어 있습니다. 목표는 주입 된 IPrincipal을 통해 사용할 수 있습니다.

이 문제를 해결하기 위해 내 IPrincipal을 ClaimsTransformer에 추가하고 TransformAsync 입력 매개 변수에서 클레임을 복제하고 UserId 및 TenantId를 추가합니다. 이 작동하지만, 내가 가지고있는 문제는 주장이 삭제되는 이유는 ClaimsTransformer을 실행하고 나는 추가해야 할 이유 내가 같은 장소에

답변

1

이었다 해킹 때 이해하지 못하는 것입니다. 나는 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); 
    } 

시작

IPrincipal DI

을 제거하기 위해

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddTransient<IClaimsTransformation, ClaimsTransformer>(); services.AddAuthentication(IISDefaults.AuthenticationScheme); services.AddAuthorization(options => { options.AddPolicy("SystemAdminOnly", policy => policy.RequireClaim(ClaimTypes.Role, "SystemAdmin")); }); 

했다 그리고 그것은 작동한다!