ASP.NET Core에서 리소스 기반의 권한 부여Resource-based authorization in ASP.NET Core

권한 부여 전략 액세스 되는 리소스에 따라 달라 집니다.Authorization strategy depends upon the resource being accessed. Author 속성에 문서를 가정 합니다.Consider a document which has an author property. 작성자만 문서를 업데이트할 수 있습니다.Only the author is allowed to update the document. 따라서 문서 권한 부여 평가 하기 전에 데이터 저장소에서 검색 해야 합니다.Consequently, the document must be retrieved from the data store before authorization evaluation can occur.

특성 평가 데이터 바인딩 전에 페이지 처리기 또는 문서를 로드 하는 작업의 실행 하기 전에 발생 합니다.Attribute evaluation occurs before data binding and before execution of the page handler or action which loads the document. 이러한 이유로, 사용한 선언적 권한 부여는 [Authorize] 특성으로 충분 하지 않습니다.For these reasons, declarative authorization with an [Authorize] attribute won't suffice. 대신, 사용자 지정 권한 부여 메서드를 호출할 수 있습니다—스타일 명령적 권한 부여 라고 합니다.Instead, you can invoke a custom authorization method—a style known as imperative authorization.

사용 하 여는 앱 샘플 (다운로드 하는 방법)이이 항목에서 설명 하는 기능을 탐색할 수 있습니다.Use the sample apps (how to download) to explore the features described in this topic.

권한 부여에 의해 보호 되는 사용자 데이터와 ASP.NET Core 응용 프로그램 만들기 리소스 기반 권한 부여를 사용 하는 샘플 앱을 포함 합니다.Create an ASP.NET Core app with user data protected by authorization contains a sample app that uses resource-based authorization.

필수 권한 부여를 사용 하 여Use imperative authorization

권한 부여로 구현 됩니다는 IAuthorizationService 내에서 서비스 컬렉션에 등록 하 고 서비스는 Startup 클래스입니다.Authorization is implemented as an IAuthorizationService service and is registered in the service collection within the Startup class. 서비스를 통해 제공할 종속성 주입 페이지 처리기 또는 작업에 있습니다.The service is made available via dependency injection to page handlers or actions.

public class DocumentController : Controller
{
    private readonly IAuthorizationService _authorizationService;
    private readonly IDocumentRepository _documentRepository;

    public DocumentController(IAuthorizationService authorizationService,
                              IDocumentRepository documentRepository)
    {
        _authorizationService = authorizationService;
        _documentRepository = documentRepository;
    }

IAuthorizationService 에 두 개의 AuthorizeAsync 메서드 오버 로드: 리소스와 정책 이름 및 다른 리소스와 평가 하기 위한 요구 사항 목록이 수락 하나 수락 합니다.IAuthorizationService has two AuthorizeAsync method overloads: one accepting the resource and the policy name and the other accepting the resource and a list of requirements to evaluate.

Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user,
                          object resource,
                          IEnumerable<IAuthorizationRequirement> requirements);
Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user,
                          object resource,
                          string policyName);

다음 예제에서는 보안을 유지 하도록 리소스는 사용자 지정에 로드 됩니다 Document 개체입니다.In the following example, the resource to be secured is loaded into a custom Document object. AuthorizeAsync 오버 로드는 현재 사용자가 제공 된 문서를 편집할 수 있는지 여부를 확인 하기 위해 호출 된 합니다.An AuthorizeAsync overload is invoked to determine whether the current user is allowed to edit the provided document. 사용자 지정 "EditPolicy" 권한 부여 정책에 대 한 결정으로 구분 됩니다.A custom "EditPolicy" authorization policy is factored into the decision. 참조 사용자 지정 정책 기반 권한 부여 권한 부여 정책 만들기에 대 한 자세한 합니다.See Custom policy-based authorization for more on creating authorization policies.

참고

다음 코드 샘플 인증을 실행 하는 것으로 가정 하 고 집합의 User 속성입니다.The following code samples assume authentication has run and set the User property.

public async Task<IActionResult> OnGetAsync(Guid documentId)
{
    Document = _documentRepository.Find(documentId);

    if (Document == null)
    {
        return new NotFoundResult();
    }

    var authorizationResult = await _authorizationService
            .AuthorizeAsync(User, Document, "EditPolicy");

    if (authorizationResult.Succeeded)
    {
        return Page();
    }
    else if (User.Identity.IsAuthenticated)
    {
        return new ForbidResult();
    }
    else
    {
        return new ChallengeResult();
    }
}

리소스 기반 처리기 작성Write a resource-based handler

리소스 기반 권한 부여 보다 큰 차이가 없습니다.에 대 한 처리기를 작성 일반 요구 사항 처리기 작성합니다.Writing a handler for resource-based authorization isn't much different than writing a plain requirements handler. 사용자 지정 요구 사항 클래스를 만들고 요구 사항 처리기 클래스를 구현 합니다.Create a custom requirement class, and implement a requirement handler class. 처리기 클래스 요구 사항 및 리소스 종류를 지정합니다.The handler class specifies both the requirement and resource type. 예를 들어 한 처리기를 활용 하는 SameAuthorRequirement 요구 사항 및 Document 리소스 모양은 다음과 같습니다.For example, a handler utilizing a SameAuthorRequirement requirement and a Document resource looks as follows:

public class DocumentAuthorizationHandler : 
    AuthorizationHandler<SameAuthorRequirement, Document>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                   SameAuthorRequirement requirement,
                                                   Document resource)
    {
        if (context.User.Identity?.Name == resource.Author)
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

public class SameAuthorRequirement : IAuthorizationRequirement { }

요구 사항 및 처리기에 등록 된 Startup.ConfigureServices 메서드:Register the requirement and handler in the Startup.ConfigureServices method:

services.AddMvc();

services.AddAuthorization(options =>
{
    options.AddPolicy("EditPolicy", policy =>
        policy.Requirements.Add(new SameAuthorRequirement()));
});

services.AddSingleton<IAuthorizationHandler, DocumentAuthorizationHandler>();
services.AddSingleton<IAuthorizationHandler, DocumentAuthorizationCrudHandler>();
services.AddScoped<IDocumentRepository, DocumentRepository>();

운영 요구 사항Operational requirements

CRUD (만들기, 읽기, 업데이트, 삭제) 작업의 결과에 따라 결정을 수행 하면 사용 하 여는 OperationAuthorizationRequirement 도우미 클래스입니다.If you're making decisions based on the outcomes of CRUD (Create, Read, Update, Delete) operations, use the OperationAuthorizationRequirement helper class. 이 클래스를 사용 하면 각 작업 유형에 대해 개별 클래스 대신 단일 처리기를 작성할 수 있습니다.This class enables you to write a single handler instead of an individual class for each operation type. 이 기능을 사용 하려면 일부 작업 이름을 제공 합니다.To use it, provide some operation names:

public static class Operations
{
    public static OperationAuthorizationRequirement Create =
        new OperationAuthorizationRequirement { Name = nameof(Create) };
    public static OperationAuthorizationRequirement Read =
        new OperationAuthorizationRequirement { Name = nameof(Read) };
    public static OperationAuthorizationRequirement Update =
        new OperationAuthorizationRequirement { Name = nameof(Update) };
    public static OperationAuthorizationRequirement Delete =
        new OperationAuthorizationRequirement { Name = nameof(Delete) };
}

처리기는 다음과 같이 사용 하 여 구현 된 OperationAuthorizationRequirement 요구 사항 및 Document 리소스:The handler is implemented as follows, using an OperationAuthorizationRequirement requirement and a Document resource:

public class DocumentAuthorizationCrudHandler :
    AuthorizationHandler<OperationAuthorizationRequirement, Document>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                   OperationAuthorizationRequirement requirement,
                                                   Document resource)
    {
        if (context.User.Identity?.Name == resource.Author &&
            requirement.Name == Operations.Read.Name)
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

이전 처리기 리소스, 사용자의 id 및 요구 사항의를 사용 하 여 작업의 유효성을 검사 Name 속성입니다.The preceding handler validates the operation using the resource, the user's identity, and the requirement's Name property.

작업 리소스 처리기를 호출 하려면 작업을 호출할 때 지정 AuthorizeAsync 페이지 처리기의 동작입니다.To call an operational resource handler, specify the operation when invoking AuthorizeAsync in your page handler or action. 다음 예제에서는 인증 된 사용자가 제공 된 문서를 볼 수 있는지 여부를 결정 합니다.The following example determines whether the authenticated user is permitted to view the provided document.

참고

다음 코드 샘플 인증을 실행 하는 것으로 가정 하 고 집합의 User 속성입니다.The following code samples assume authentication has run and set the User property.

public async Task<IActionResult> OnGetAsync(Guid documentId)
{
    Document = _documentRepository.Find(documentId);

    if (Document == null)
    {
        return new NotFoundResult();
    }

    var authorizationResult = await _authorizationService
            .AuthorizeAsync(User, Document, Operations.Read);

    if (authorizationResult.Succeeded)
    {
        return Page();
    }
    else if (User.Identity.IsAuthenticated)
    {
        return new ForbidResult();
    }
    else
    {
        return new ChallengeResult();
    }
}

권한 부여에 성공 하면 문서를 보기 위한 페이지가 반환 됩니다.If authorization succeeds, the page for viewing the document is returned. 경우 권한 부여 실패 하지만 사용자가 인증 되 면 반환 ForbidResult 권한 부여에 실패 한 모든 인증 미들웨어에 알립니다.If authorization fails but the user is authenticated, returning ForbidResult informs any authentication middleware that authorization failed. A ChallengeResult 인증을 수행 해야 하는 경우 반환 됩니다.A ChallengeResult is returned when authentication must be performed. 대화형 브라우저 클라이언트에는 사용자를 로그인 페이지로 리디렉션합니다 적절 한 수 있습니다.For interactive browser clients, it may be appropriate to redirect the user to a login page.