권한부여: 리소스 기반 권한부여
- 본 번역문서의 원문은 Resource Based Authorization docs.microsoft.com 입니다.
- 본 번역문서는 ASP.NET Core 보안 : 리소스 기반 권한부여 www.taeyo.net 에서도 함께 제공됩니다.
접근하려는 리소스에 따라서 권한부여의 결과가 달라지는 경우도 많습니다.
예를 들어, 문서에 작성자 속성이 존재한다고 가정해보겠습니다.
만약, 문서의 작성자만 문서를 갱신할 수 있어야 한다면, 권한부여를 위한 평가를 수행하기 전에 먼저 문서 저장소에서 리소스, 즉 문서부터 로드해야 합니다.
그러나 어트리뷰트의 평가는 데이터 바인딩 이전에, 그리고 액션 내부에 작성된 코드가 리소스를 로드하기 이전에 수행되기 때문에, 이런 유형의 작업은 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<MyRequirement, Document>
{
public override Task HandleRequirementAsync(AuthorizationHandlerContext context,
MyRequirement requirement,
Document resource)
{
// Validate the requirement against the resource and identity.
return Task.CompletedTask;
}
}
작성한 처리기를 ConfigureServices
메서드에서 등록해야 한다는 점도 잊지 마시기 바랍니다:
services.AddSingleton<IAuthorizationHandler, DocumentAuthorizationHandler>();
작업별 요구사항
읽기, 쓰기, 수정, 삭제 같은 작업을 기반으로 권한을 부여해야 하는 경우에는 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<OperationAuthorizationRequirement, Document>
{
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 상태 코드를 반환하거나 대화형 브라우저 클라이언트의 경우 사용자를 로그인 페이지로 재지정하는 등과 같은 적절한 응답을 반환할 수 있음을 알려줍니다.
- 권한부여: 개요 2017-01-14 08:00
- 권한부여: 간단한 권한부여 2017-01-14 11:00
- 권한부여: 역할 기반 권한부여 2017-01-14 14:00
- 권한부여: 클레임 기반 권한부여 2017-01-15 08:00
- 권한부여: 사용자 지정 정책 기반 권한부여 2017-01-15 11:00
- 권한부여: 요구사항 처리기와 의존성 주입 2017-01-15 14:00
- 권한부여: 리소스 기반 권한부여 2017-01-16 08:00
- 권한부여: 뷰 기반 권한부여 2017-01-16 11:00
- 권한부여: 스키마별 신원 제한 2017-01-16 14:00
- 인증: ASP.NET Core Identity 살펴보기 2017-01-30 08:00
- 인증: Facebook, Google 및 기타 외부 공급자를 이용한 인증 활성화시키기 2017-02-13 08:00
- 인증: Facebook 인증 구성하기 2017-02-13 11:00
- 인증: Twitter 인증 구성하기 2017-02-20 08:00
- 인증: Google 인증 구성하기 2017-02-20 11:00
- 인증: Microsoft 계정 인증 구성하기 2017-02-20 14:00
- 인증: 계정 확인 및 비밀번호 복구 2017-03-06 08:00
- 인증: SMS를 이용한 2단계 인증 2017-03-13 08:00
- 인증: ASP.NET Core Identity 없이 Cookie 미들웨어 사용하기 2017-03-20 08:00
- 데이터 보호: 데이터 보호 개요 2017-03-27 08:00
- 데이터 보호: 데이터 보호 API 시작하기 2017-03-29 08:00
- 데이터 보호: 소비자 APIs 개요 2017-03-31 08:00
- 데이터 보호: 용도 문자열 2017-04-03 08:00
- 데이터 보호: ASP.NET Core의 용도 계층 구조 및 다중-테넌트(Multi-Tenancy) 2017-04-05 08:00
- 데이터 보호: 비밀번호 해싱 2017-04-07 08:00
- 데이터 보호: 보호된 페이로드의 수명 제한하기 2017-04-10 08:00
- 테이터 보호: 키가 취소된 페이로드의 보호 해제하기 2017-04-12 08:00
- 데이터 보호: 데이터 보호 구성하기 2017-04-14 08:00
- 데이터 보호: 키 관리 및 수명 기본 설정 2017-04-17 08:00
- 데이터 보호: 머신 수준 정책 2017-04-19 08:00
- 데이터 보호: 비-DI 인식 시나리오 2017-04-21 08:00
- 호환성: 응용 프로그램 간 인증 쿠키 공유하기 2017-05-12 08:00
- 호환성: ASP.NET의 <machineKey> 요소 대체하기 2017-05-16 08:00
- 교차 원본 요청 활성화시키기 (CORS) 2017-05-17 08:00
- ASP.NET Core 응용 프로그램에 SSL 적용하기 2017-05-18 08:00
- 개발 중 민감한 응용 프로그램 정보 안전하게 저장하기 2017-05-19 08:00