login register Sysop! about ME  
qrcode
    최초 작성일 :    2017년 02월 22일
  최종 수정일 :    2017년 02월 22일
  작성자 :    soggun
  편집자 :    soggun (송원석)
  읽음수 :    8,267

강좌 목록으로 돌아가기

필자의 잡담~

이번 컬럼은 ASP.NET Core 보안 강좌의 7번째 글, 리소스 기반 권한부여에 대한 글입니다.

모든 컬럼은 http://docs.asp.net의 내용을 참고하여 번역한 것입니다. Windows 뿐만 아니라 Linxu, OS X에서도 동작하는 완전한 크로스 플랫폼 서버기술인 ASP.NET Core! 기대해 주세요.

본 번역문서는 개인적인 취지로 번역되어 제공되는 문서로, 원문을 비롯한 모든 저작권은 마이크로소프트사에 있습니다. 마이크로소프트사의 요청이 있을 경우, 언제라도 게시가 중단될 수 있습니다. 본 번역문서에는 오역이 포함되어 있을 수 있으며 주석도 번역자 개인의 견해일뿐입니다. 마이크로소프트사는 본 문서의 번역된 내용에 대해 일체의 보장을 하지 않습니다. 번역이 완료된 뒤에도 제품이 업그레이드 되거나 기능이 변경됨에 따라 원문도 변경되거나 보완되었을 수 있으므로 참고하시기 바랍니다.

원문: https://docs.microsoft.com/en-us/aspnet/core/security/authorization/resourcebased

리소스 기반 권한부여

접근하려는 리소스에 따라서 권한부여의 결과가 달라지는 경우도 많습니다. 예를 들어, 문서에 작성자 속성이 존재한다고 가정해보겠습니다. 만약, 문서의 작성자만 문서를 갱신할 수 있어야 한다면, 권한부여를 위한 평가를 수행하기 전에 먼저 문서 저장소에서 리소스, 즉 문서부터 로드해야 합니다. 그러나 어트리뷰트의 평가는 데이터 바인딩 이전에, 그리고 액션 내부에 작성된 코드가 리소스를 로드하기 이전에 수행되기 때문에, 이런 유형의 작업은 Authorize 어트리뷰트로는 처리할 수가 없습니다. 이 경우에는 어트리뷰트 방식의 선언적 권한부여 대신, 코드 내에서 개발자가 권한부여 함수를 호출하는 명령형 권한부여를 사용해야 합니다.

코드를 이용한 권한부여

권한부여는 IAuthorizationService 인터페이스를 구현하는 서비스로 작성되어 서비스 컬렉션에 등록되며, 의존성 주입을 통해서 컨트롤러에서 접근할 수 있습니다.

public class DocumentController : Controller
{
    IAuthorizationService _authorizationService;

    public DocumentController(IAuthorizationService authorizationService)
    {
        _authorizationService = authorizationService;
    }
}

IAuthorizationService 인터페이스는 두 가지 메서드를 갖고 있는데, 그 중 한 메서드에는 리소스와 정책 이름을 전달할 수 있고, 다른 메서드에는 리소스와 평가할 요구사항들의 목록을 전달할 수 있습니다.

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

권한부여 서비스를 호출하려면 액션 내부에서 리소스를 로드한 다음, 상황에 맞는 AuthorizeAsync 메서드의 오버로드 버전을 호출하면 됩니다. 가령 다음과 같습니다:

public async Task<IActionResult> Edit(Guid documentId)
{
    Document document = documentRepository.Find(documentId);

    if (document == null)
    {
        return new HttpNotFoundResult();
    }

    if (await authorizationService.AuthorizeAsync(User, document, "EditPolicy"))
    {
        return View(document);
    }
    else
    {
        return new ChallengeResult();
    }
}

리소스 기반 처리기 작성하기

리소스 기반 권한부여를 위한 처리기를 작성하는 방법은 일반적인 요구사항 처리기의 작성 방법과 크게 다르지 않습니다. 먼저 요구사항을 생성한 다음, 기존처럼 요구사항 뿐만 아니라 이번에는 리소스 형식까지 지정해서 해당 요구사항에 대한 처리기를 구현합니다. 예를 들어, Document 리소스를 전달받는 처리기는 다음과 같은 형태를 갖게 됩니다:

public class DocumentAuthorizationHandler : AuthorizationHandler<MyRequirementDocument>
{
    public override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                MyRequirement requirement,
                                                Document resource)
    {
        // Validate the requirement against the resource and identity.

        return Task.CompletedTask;
    }
}

작성한 처리기를 ConfigureServices 메서드에서 등록해야 한다는 점도 잊지 마시기 바랍니다:

services.AddSingleton<IAuthorizationHandlerDocumentAuthorizationHandler>();

작업별 요구사항

읽기, 쓰기, 수정, 삭제 같은 작업을 기반으로 권한부여 결정을 내려야 하는 경우에는 Microsoft.AspNetCore.Authorization.Infrastructure 네임스페이스의 OperationAuthorizationRequirement 클래스를 활용할 수 있습니다. 기본적으로 제공되는 이 요구사항 클래스를 활용하면 각각 작업들마다 개별적인 클래스를 만드는 대신, 작업 이름을 매개변수로 전달하는 단일 처리기를 만들 수 있습니다. 이 클래스를 사용하기 위해서는 먼저 필요한 작업들의 이름을 정의해야 합니다:

public static class Operations
{
    public static OperationAuthorizationRequirement Create =
        new OperationAuthorizationRequirement { Name = "Create" };
    public static OperationAuthorizationRequirement Read =
        new OperationAuthorizationRequirement { Name = "Read" };
    public static OperationAuthorizationRequirement Update =
        new OperationAuthorizationRequirement { Name = "Update" };
    public static OperationAuthorizationRequirement Delete =
        new OperationAuthorizationRequirement { Name = "Delete" };
}

그러면 다음과 같이 처리기를 구현할 수 있습니다. 이 예제 처리기는 임의의 Document 클래스를 리소스로 사용한다고 가정하고 있습니다:

public class DocumentAuthorizationHandler : 
    AuthorizationHandler<OperationAuthorizationRequirementDocument>
{
    public override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                OperationAuthorizationRequirement requirement,
                                                Document resource)
    {
        // Validate the operation using the resource, the identity and
        // the Name property value from the requirement.

        return Task.CompletedTask;
    }
}

이 처리기의 코드를 살펴보면 OperationAuthorizationRequirement 클래스를 사용하고 있음을 알 수 있습니다. 그리고 처리기 내부의 코드에서 평가를 수행할 때는 전달된 요구사항의 Name 속성을 반드시 고려해야 합니다.

작업별 리소스 처리기를 호출하기 위해서는 액션에서 AuthorizeAsync 메서드를 호출할 때 다음과 같이 대상 작업을 지정하면 됩니다:

if (await authorizationService.AuthorizeAsync(User, document, Operations.Read))
{
    return View(document);
}
else
{
    return new ChallengeResult();
}

이 예제 코드는 현재 document 인스턴스를 대상으로 사용자가 읽기 작업을 수행할 수 있는지 여부를 확인합니다. 권한부여에 성공하면 해당 문서에 대한 뷰가 반환됩니다. 그러나 권한부여에 실패하면 ChallengeResult가 반환되어, 모든 인증 미들웨어에게 권한부여가 실패했으며 미들웨어에서 401 또는 403 상태 코드를 반환하거나 대화형 브라우저 클라이언트의 경우 사용자를 로그인 페이지로 재지정하는 등과 같은 적절한 응답을 반환할 수 있음을 알려줍니다.


authored by


 
 
.NET과 Java 동영상 기반의 교육사이트

로딩 중입니다...

서버 프레임워크 지원 : NeoDEEX
based on ASP.NET 3.5
Creative Commons License
{5}
{2} 읽음   :{3} ({4})