2

여기 여러 개념으로 머리를 감싸려고하지만이 질문이 너무 광범위하지 않기를 바라고 있습니다. 기본적으로 우리가 시도하는 것은 역할 클레임을 잠금 권한으로 사용하는 것입니다 API가 다운되었지만 access_token이 너무 커지는 것을 발견했습니다.OpenIdConnect access_token 크기 및 클레임 서버 쪽

우리는 서버 측에서 OpenIddict와 ASP.NET Identity 3을 사용하고 있습니다. 우리는 기본 AspNetRoleClaims 테이블을 구현하여 각 역할에 대한 클레임을 사용 권한으로 저장합니다.

우리의 주장을 포함하는 우리의 access_token이 매우 큰되고

Custom Policy Based Authorization

내가 발견하고 주요 문제가된다 : 다음과 같이

우리는 사용자 정의 정책 클레임 기반 인증을 사용하여 우리의 API 엔드 포인트를 잠급니다. 클레임 유형 및 값을 클레임 크기를 줄이기 위해 데이터베이스에서 매우 작게 만들려고합니다. 우리에게는 기본 CRUD 유형 권한 구성표가 있으므로 SPA 클라이언트 응용 프로그램의 각 "모듈"또는 화면에는 4 가지 권한이 있습니다. 애플리케이션에 모듈을 더 많이 추가할수록 access_token에서 요청이 늘어나고 Authorization Bearer 헤더가 매우 커지고 있습니다. 앱이 성장함에 따라 확장 성이 크게 떨어지는 것이 걱정됩니다.

은 그래서 주장은 access_token이에 포함 된 내가 이런 사용자 정의 정책에 잠겨 내 엔드 포인트 ...

[Authorize(Policy="MyModuleCanRead")] 
[HttpGet] 
public IEnumerable<MyViewModel> Get() 

을 쳤을 때 나는 다음 내 ASP.NET 신원 사용자 및 사용자에 액세스 할 수 있습니다 AuthorizationHandler에서 클레임.

분명히 궁금한 점이 있으시면 미리 죄송합니다. - 사용자 지정 정책 기반 인증을 받으려면 id_token 또는 access_token에 전화를 걸려면 클레임이 반드시 필요합니다. 핸들러?

access_token에서 클레임을 제거하면 AuthorizationHandler 코드에 문제가 발생하지 않고 사용자 지정 정책으로 잠긴 엔드 포인트에 액세스 할 수 없습니다.

사용자 지정 클레임 정책을 사용할 수 있지만 권한 부여 처리기 내에서 클레임을 확인하는 실제 코드가 있으면 각 HTTP 요청과 함께 클레임이 전달되지 않지만 서버 측에서 페치되는 것은 아닌지 궁금합니다. 권한 부여 쿠키 또는 데이터베이스에서.

* 내가 찾던 바로 무엇을 달성 쿠키에서 추가 역할 주장을 제거하는 방법에 대한 의견과 함께 승인 처리기를 사용하여 UPDATE *

Pintpoint의 대답.

다른 사람에게 도움이되는 경우 - 여기에 UserClaimsPrincipalFactory를 재정의하고 역할 클레임이 쿠키에 기록되지 않도록하는 코드가 있습니다. 이 정의를 사용할 수있는 경우

public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole> 
{ 
    public AppClaimsPrincipalFactory(UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor) 
    { 
    } 
    public override async Task<ClaimsPrincipal> CreateAsync(ApplicationUser user) 
    { 
     if (user == null) 
     { 
      throw new ArgumentNullException(nameof(user)); 
     } 
     var userId = await UserManager.GetUserIdAsync(user); 
     var userName = await UserManager.GetUserNameAsync(user); 
     var id = new ClaimsIdentity(Options.Cookies.ApplicationCookieAuthenticationScheme, 
      Options.ClaimsIdentity.UserNameClaimType, 
      Options.ClaimsIdentity.RoleClaimType); 
     id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId)); 
     id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName)); 
     if (UserManager.SupportsUserSecurityStamp) 
     { 
      id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType, 
       await UserManager.GetSecurityStampAsync(user))); 
     } 

     // code removed that adds the role claims 

     if (UserManager.SupportsUserClaim) 
     { 
      id.AddClaims(await UserManager.GetClaimsAsync(user)); 
     } 
     return new ClaimsPrincipal(id); 
    } 
} 

답변

1

내가 궁금 오전 (I 권한과 쿠키 (들) 및 요청 헤더 많은 역할 주장을했다가 너무 큽니다되고 있었다) 정책을 주장하지만, 실제 코드가 그 클레임이 각 HTTP 요청과 함께 전달되지 않지만 권한 부여 쿠키 또는 데이터베이스에서 서버 측으로 반입되도록 권한 부여 처리기 내의 클레임을 확인합니다.

확실히 가능합니다. 다음과 같이 할 수 있습니다.

public class Startup 
{ 
    public void ConfigureServices(IServiceCollection services) 
    { 
     services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>(); 

     services.AddAuthorization(options => 
     { 
      options.AddPolicy("Has-Edit-User-Profiles-Permission", builder => 
      { 
       builder.RequirePermission("Edit-User-Profiles"); 
      }); 
     }); 
    } 
} 

public class PermissionAuthorizationRequirement : IAuthorizationRequirement 
{ 
    public PermissionAuthorizationRequirement(string permission) 
    { 
     if (string.IsNullOrEmpty(permission)) 
     { 
      throw new ArgumentException("The permission cannot be null or empty.", nameof(permission)); 
     } 

     Permission = permission; 
    } 

    public string Permission { get; set; } 
} 

public class PermissionAuthorizationHandler : 
    AuthorizationHandler<PermissionAuthorizationRequirement> 
{ 
    private readonly UserManager<ApplicationUser> _userManager; 

    public PermissionAuthorizationHandler(UserManager<ApplicationUser> userManager) 
    { 
     if (userManager == null) 
     { 
      throw new ArgumentNullException(nameof(userManager)); 
     } 

     _userManager = userManager; 
    } 

    protected override async Task HandleRequirementAsync(
     AuthorizationHandlerContext context, 
     PermissionAuthorizationRequirement requirement) 
    { 
     if (context.User == null) 
     { 
      return; 
     } 

     var user = await _userManager.GetUserAsync(context.User); 
     if (user == null) 
     { 
      return; 
     } 

     // Use whatever API you need to ensure the user has the requested permission. 
     if (await _userManager.IsInRoleAsync(user, requirement.Permission)) 
     { 
      context.Succeed(requirement); 
     } 
    } 
} 

public static class PermissionAuthorizationExtensions 
{ 
    public static AuthorizationPolicyBuilder RequirePermission(
     this AuthorizationPolicyBuilder builder, string permission) 
    { 
     if (builder == null) 
     { 
      throw new ArgumentNullException(nameof(builder)); 
     } 

     if (string.IsNullOrEmpty(permission)) 
     { 
      throw new ArgumentException("The permission cannot be null or empty.", nameof(permission)); 
     } 

     return builder.AddRequirements(new PermissionAuthorizationRequirement(permission)); 
    } 
} 
+0

Thanks Pinpoint - 좋은 예입니다. 이것은 대부분의 역할 클레임과 함께 작동합니다. id_token 및 access_token에 저장되지 않도록 제거 할 수 있습니다. 그러나 AspNetRoleClaims 테이블을 사용하고 있기 때문에 Identity는 나에게 "기본 제공"기능을 제공합니다. 이러한 많은 클레임은 여전히 ​​ID 인증 쿠키에 저장되며, 이제는 로그 아웃 할 때 HTTP 요청 헤더가 너무 큰. – user1750537

+0

내가이 역할 클레임이 Identity 쿠키에 채워지는 것을 막을 수 있는지 궁금하다. 그리고 아마도 PermissionAuthorizationHandler를 치면 직접 쿼리 할 수있는 방법이있을 것이다. 아마도 가장 간단한 해결책은 AspNetRoleClaims 테이블을 전혀 사용하지 않고 내 자신의 사용자 지정 권한 테이블을 사용하고 위와 같이 PermissionAuthorizationHandler에서 가져 오는 것입니다. – user1750537

+1

@ user1750537 예 할 수 있습니다. 하나의 옵션은 자신 만의'IUserClaimsPrincipalFactory' 파일을 만들고 DI 컨테이너에 등록하는 것입니다 : https://github.com/aspnet/Identity/blob/dev/src/Microsoft.AspNetCore.Identity/UserClaimsPrincipalFactory.cs. 또는'CreateTicketAsync' 메소드를 조정하여 역할 클레임을 제거 할 수도 있습니다. – Pinpoint