DDD CQRS-쿼리 및 명령 당 권한 부여


15

요약

CQRS / DDD의 권한 부여는 명령 / 조회마다 구현되어야합니까?

DDD CQRS 패턴을 다소 엄격하게 사용하는 온라인 응용 프로그램을 처음으로 개발하고 있습니다. 나는 약간의 문제에 부딪쳤다.

내가 만들고있는 응용 프로그램은 사람들이 원장을 만들 수있게하고 직원과 같은 다른 사람들이보고 / 편집 / 삭제할 수 있도록하는 원장 응용 프로그램입니다. 원장의 작성자는 자신이 작성한 원장의 액세스 권한을 편집 할 수 있어야합니다. 소유권을 바꿀 수도 있습니다. 도메인에는 두 개의 집계 TLedgerTUser가 있습니다.

보안, 권한 부여 등에 관한 DDD / CQRS 키워드로 많은 게시물을 읽었습니다 . 보안 응용 프로그램을 작성하지 않는 한 대부분은 권한 부여가 Generic Subdomain 이라고 언급했습니다 .

이 경우 핵심 도메인 은 거래, 밸런싱 및 계정에 관심이 있는 회계 도메인 입니다. 그러나 원장에 대한 세분화 된 액세스를 관리 할 수있는 기능도 필요합니다. DDD / CQRS 용어로 이것을 디자인하는 방법이 궁금합니다.

명령은 어디에서나 유비쿼터스 언어의 일부라고 DDD 튜토리얼에 나와 있습니다. 그들은 의미가 있습니다. 그것들은 "실제"를 나타내는 구체적인 행동입니다.

이러한 모든 명령과 쿼리는 사용자가 "실제"로 실행하는 실제 작업이므로 권한 부여 구현은 이러한 모든 "명령"및 "쿼리"와 결합되어야합니까? 예를 들어, 사용자에게는 TLedger.addTransaction ()을 실행할 권한이 있지만 TLedger.removeTransaction ()은 없습니다. 또는 사용자는 "getTransactions ()"가 아닌 "getSummaries ()"쿼리를 실행할 수 있습니다.

3 차원 매핑은 액세스 권한을 결정하기 위해 user-ledger-command 또는 user-ledger-query 형식으로 존재합니다.

또는 분리 된 방식으로 "permissions"라는 이름이 사용자에게 등록됩니다. 그런 다음 특정 명령에 대해 매핑되는 권한 예를 들어 권한 "ManageTransactions"는 사용자가 "AddTransaction ()", "RemoveTransaction ()"등을 실행할 수 있도록합니다.

  1. 권한 매핑 사용자-> 원장-> 명령 / 쿼리

  2. 권한 맵핑 사용자-> 원장-> 권한-> 명령 / 조회

이것이 질문의 첫 번째 부분입니다. 즉, CQRS / DDD의 권한 부여는 명령 또는 쿼리마다 구현되어야합니까? 또는 권한을 명령에서 분리해야합니까?

둘째, 권한 기반 인증에 관한 것입니다. 사용자는 자신의 원장 또는 자신이 관리 할 수있는 원장에 대한 권한을 관리 할 수 ​​있어야합니다.

  1. 원장에서 권한 부여 관리 명령이 발생합니다

grantPermission (), revokePermission () 등과 같은 이벤트 / 명령 / 처리기를 Ledger 집계 에 추가하려고 생각했습니다 .이 경우 해당 규칙을 적용하면 명령 처리기에서 발생합니다. 그러나이를 위해서는 모든 명령에 해당 명령을 발행 한 사용자의 ID가 포함되어야합니다. 그런 다음 해당 사용자가 해당 명령을 실행할 수있는 권한이 있는지 TLedger에 체크인합니다.

예를 들면 다음과 같습니다.

class TLedger{ 
    function addTransactionCmdHandler(cmd){
        if (!this.permissions.exist(user, 'addTransaction')
            throw new Error('Not Authorized');
    }
}
  1. 사용자의 권한 관리 명령

다른 방법은 권한을 TUser에 포함시키는 것입니다. TUser는 권한 세트를 갖습니다. 그런 다음 TLedger 명령 핸들러에서 사용자를 검색하여 명령을 실행할 권한이 있는지 확인합니다. 그러나 이것은 모든 TLedger 명령에 대해 TUser 집계를 가져와야합니다.

class TAddTransactionCmdHandler(cmd) {
    this.userRepository.find(cmd.userId)
    .then(function(user){
        if (!user.can(cmd)){
            throw new Error('Not authorized');
        }
        return this.ledgerRepository.find(cmd.ledgerId);
    })
    .then(function(ledger){
        ledger.addTransaction(cmd);
    })

}
  1. 서비스가있는 다른 도메인

또 다른 가능성은 다른 권한 부여 도메인을 완전히 모델링하는 것입니다. 이 도메인은 액세스 권한, 권한 부여 등에 관심이 있습니다. 계정 하위 도메인은 서비스를 사용하여이 권한 부여 도메인에 액세스합니다 AuthorizationService.isAuthorized(user, command).

class TAddTransactionCmdHandler(cmd) {
    authService.isAuthorized(cmd)
    .then(function(authorized){
        if (!authorized) throw new Error('Not authorized');
        return this.ledgerRepository.find(cmd.ledgerId)
    })
    .then(function(){
        ledger.addTransaction(cmd);
    })

}

가장 "DDD / CQRS"방식은 무엇입니까?


1
좋은 질문-비슷한 문제를 해결하려고 노력했지만 직접 언급 한 문헌은 없습니다. 나는 당신의 질문의 후반부에 약간 혼란 스러웠습니다. 권한 관리 (퍼미션 추가 또는 제거)를 어디에 두어야하는지 궁금해 보였지만, 표시된 예제는 트랜잭션을 추가하기위한 것이므로, 하반기에는 "어떻게 권한을 쿼리해야하는지"를 묻는 것처럼 보입니다. 그 부분을 명확히 할 수 있습니까?
emragins

각 트랜잭션에는 실행 정책이있을 수 있습니다. 각 사용자는 하나 이상의 그룹에 속해야하며, 각 그룹에는 허용되는 트랜잭션을 지정하는 액세스 프로파일이 있습니다. 런타임시 트랜잭션을 실행하기 전에 실행중인 사용자의 집계 된 프로필에 대해 정책을 확인합니다. 물론 이것은 말보다 쉽습니다.
NoChance

답변:


5

첫 번째 질문에 대해서는 비슷한 문제로 고심하고 있습니다. 점점 더 3 단계 인증 체계에 기울고 있습니다.

1)의 명령 / 쿼리 수준에서 권한 부여 "이 사용자는 않는다 지금까지 이 명령을 실행할 수있는 권한이?" MVC 앱에서는 아마도 컨트롤러 수준에서 처리 될 수 있지만 현재 사용자와 실행중인 명령을 기반으로 권한 저장소를 쿼리하는 일반적인 프리 핸들러를 선택합니다.

2) "이 사용자에게"이 엔티티에 액세스 할 수있는 권한이 있습니까? "라는 응용 프로그램 서비스 내에서의 권한 부여 내 경우에는 아마도 저장소의 필터를 사용하여 암시적인 검사가 될 수 있습니다. 기본적으로 OrganizationId를 조금 더 세분화 한 TenantId입니다.

3) 엔터티의 일시적 속성 (예 : 상태)에 의존하는 권한은 도메인 내부에서 처리됩니다. (예 : "특정 사람들 만이 폐쇄 원장을 수정할 수 있습니다.") 도메인과 비즈니스 로직에 크게 의존하고 있기 때문에 도메인 내부에 넣는 것을 선호합니다.

나는이 아이디어에 대한 다른 사람들의 반응을 듣고 싶습니다. 원한다면 파쇄로 찢으십시오 (만약 당신이 할 경우 대안을 제공하십시오 :))


나는 당신이 다른 "계층"의 권한에 대해 몇 가지 유효한 점을 가지고 있다고 생각합니다. 내가 작업하고 있던 시스템에는 등록 된 사용자와 직원으로 다른 유형의 사용자가있었습니다. 명령 / 조회 핸들러 권한은 사용자 유형에 대한 기본 점검을 수행했습니다. 직원이라면 항상 통과했습니다. 등록 된 사용자 인 경우 특정 조건 (예 : 집합에 대한 권한)이 충족되는 경우에만 허용됩니다.
magnus

0

Authorization BC의 일부로 권한 부여를 구현하지만 Ledger 시스템에 작업 필터로 배포합니다. 이런 방식으로 서로 논리적으로 분리 될 수 있습니다. 원장 코드는 인증 코드를 호출 할 필요는 없지만 각 수신 요청에 대해 프로세스 내에서 고성능의 인증을받습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.