DDD 구현 : 사용자 및 권한


16

도메인 기반 디자인의 원칙을 파악하려는 작은 응용 프로그램을 만들고 있습니다. 성공하면 더 큰 프로젝트의 파일럿이 될 수 있습니다. Vaughn Vernon의 "도메인 기반 디자인 구현"책을 따라 가면서 유사하고 간단한 토론 포럼을 구현하려고합니다. 또한 github에서 IDDD 샘플을 확인했습니다. 본인의 사례에 대한 신원 및 액세스를 채택하는 데 어려움이 있습니다. 몇 가지 배경 정보를 제공하겠습니다.

  • 필자는 사용자와 권한 논리를 분리하는 이유를 뒷받침합니다. 지원 도메인이며 다른 경계 컨텍스트입니다.
  • 핵심 도메인에는 사용자, 작성자, 중재자 등이 없습니다. 서비스를 사용하여 ID 및 액세스 컨텍스트에 도달 한 후 수신 된 사용자 오브젝트를 중재자로 변환하여 작성됩니다.
  • 도메인 작업은 관련 역할을 매개 변수로 사용하여 호출됩니다. 예 :

    ModeratePost( ..., moderator);

  • 도메인 객체의 메서드는 지정된 중재자 인스턴스가 null이 아닌지 확인합니다 (ID 및 액세스 컨텍스트에서 요청한 사용자에게 중재자 역할이없는 경우 중재자 인스턴스는 null 임).

  • 어떤 경우에는 게시물을 변경하기 전에 추가 검사를 수행합니다.

    if (forum.IsModeratedby(moderator))

내 질문은 :

  • 후자의 경우 보안 문제가 핵심 영역에 다시 혼합되지 않습니까? 이전에는이 ​​책에 "제목을 게시 할 수있는 사람 또는 허용되는 조건하에있는 사람이 있습니다. 포럼은 저자가 지금 그 일을하고 있음을 알아야합니다".

  • 이 책의 역할 기반 구현은 매우 간단합니다. 중재자가 핵심 도메인 인 경우 현재 userId를 필요한 경우 중재자 인스턴스 또는 작성자로 변환하려고합니다. 서비스는 적절한 인스턴스로 응답하거나 사용자에게 필요한 역할이 없으면 널입니다. 그러나이를보다 복잡한 보안 모델에 어떻게 적용 할 수 있는지 알 수 없습니다. 현재 파일럿하려는 프로젝트에는 그룹, ACL 등이있는 다소 복잡한 모델이 있습니다.

"소유자 나 편집자 만 게시물을 편집해야합니다"와 같이 매우 복잡하지 않은 규칙이 있더라도이 방법은 고장 나거나 적어도 그것을 구현하는 올바른 방법이 보이지 않습니다.

OwnerOrEditor 인스턴스에 대한 Identity 및 Access 컨텍스트를 요청하는 것이 옳지 않다고 생각하며 핵심 도메인에서 점점 더 많은 보안 관련 클래스로 끝날 것입니다. 또한 userId뿐만 아니라 보호 된 리소스의 식별자 (게시물, 포럼 등의 ID)를 보안 컨텍스트에 전달해야합니다.이 컨텍스트는 신경 쓰지 않아야합니다 (정확합니까? )

핵심 도메인에 대한 권한을 가져 와서 도메인 객체의 방법이나 서비스에서 확인함으로써 보안 문제를 도메인과 혼합하는 것입니다.

보안 및 권한이 핵심 도메인 자체가 아닌 한 이러한 권한 관련 사항이 핵심 도메인의 일부가되어서는 안된다는 것을 읽었습니다. 위에 주어진 것과 같은 간단한 규칙이 보안을 핵심 도메인의 일부로 만드는 것을 정당화합니까?


어쩌면 여기에서 필요한 것을 찾을 수 있습니다 : stackoverflow.com/a/23485141/329660 또한, Access Control 컨텍스트가 리소스 ID 에 대해 알고 있다고해서 해당 리소스가 어떤 종류의 엔티티인지 또는 무엇인지에 대한 도메인 지식이 있다는 의미는 아닙니다. 그렇습니다.
guillaume31 년

고마워, 나는 이전에 그 게시물을 보았습니다. 제 문제는 편집이 마지막에 말하는 것입니다 : 액세스 제어를 핵심 도메인 밖으로 옮기고 싶지만 구현으로 벽에 부딪쳤다 고 생각합니다. 그러나 리소스 ID에 대한 제안은 의미가 있습니다. 핵심 도메인에서 사용자 또는 역할 개념을 사용하지 않고 구체적인 역할을 사용하기 때문에 보안 BC에서 리소스 개념을 사용하여 관련 콘크리트에 매핑 할 수 있습니다. 도메인 개념. 시도해 볼 가치가 있습니다. 감사합니다!
LittlePilgrim

링크의 코드 샘플이 최소한 "더 복잡한 보안 모델에 어떻게 적용 할 수 없는지"에 대한 답을 얻지 못 합니까?
guillaume31

내 문제는 보안 모델 자체의 구현이 아니라 더 복잡한 규칙을 도메인에 어떻게 매핑 해야하는지 알 수 없습니다. 보안 측면에서 단순한 역할 기반 모델이 아닌 경우 사용자-> 작성자 맵핑을 어떻게 변경해야합니까? 다른 컨텍스트에 리소스 ID를 전달하는 것은 효과가있을 수 HasPermissionToEdit(userId, resourceId)있지만 이러한 호출로 도메인 논리를 오염시키는 것은 옳지 않습니다. 아마도 도메인 논리를 호출하기 전에 응용 프로그램 서비스 방법에서 이것들을 확인해야합니까?
LittlePilgrim

물론 응용 프로그램 서비스에 있어야합니다 ... UserService @AccessControlList[inf3rno]링크 된 답변 과 같은 코드 부분에서 분명하다고 생각했습니다 .
guillaume31

답변:


6

실제 액세스 제어 규칙과 액세스 제어에 경계를 두는 도메인 불변량을 구분하기가 어려운 경우가 있습니다.

특히, 특정 도메인 논리 과정에서 멀리 떨어진 데이터에만 의존하는 규칙은 도메인에서 쉽게 추출 할 수 없습니다. 일반적으로 액세스 제어는 도메인 작업이 수행되기 전이나 후에 호출되지만 호출 중에는 수행되지 않습니다.

본 버논의 assert (forum.IsModeratedBy(moderator))사례는 아마도 도메인 외부에 있었을 지 모르지만 항상 실현 가능한 것은 아닙니다.

userId뿐만 아니라 보호 된 리소스의 식별자 (게시물, 포럼 등의 ID)를 보안 컨텍스트에 전달해야합니다.이 컨텍스트는 신경 쓰지 않아야합니다 (정확합니까?)

Security BC가 있고 그 논리를 처리하기를 원한다면 포럼이 무엇인지 자세히 알아야 할 필요는 없지만 다음과 같습니다.

  • "중재자"와 같은 개념에 대한 지식을 보유하고 이에 따라 액세스 권한을 부여하거나 거부 할 수 있습니다.
  • 핵심 도메인 이벤트에 등록하고 Security BC가 저장하고 사용할 수있는 간단한 (자원, AuthorizedUsers) 키 값 쌍으로 변환하는 어댑터 논리를 가질 수 있습니다.

두 답변이 유용하고 다소간 동일한 방향을 가리키고 있으므로 두 가지를 모두 올렸습니다. @ guillaume31이 Vernon의 구현에 대한 내 질문에 어느 정도 대답 했으므로 Security BC에서 리소스를 사용하는 것에 대한 힌트를 바탕으로 구현을 계속할 것입니다.
LittlePilgrim

나는 이것이 내 대답과 완전히 반대라고 생각해야합니다.
Ewan

1
어쩌면 나는 지금 너무 혼란 스러웠지만 내 해석은 (두 대답 모두) 다음과 같습니다. 1. 도메인에서 보안 문제를 유지하고 보안 BC를 서비스로 사용하십시오. 2. 도메인 객체를 호출하기 전에 서비스를 호출하십시오. 사용자 / acls에서 중재자, 작성자 등으로의 매핑을 수행합니다. moderator = securityService.GetModerator(userId, forumId) 4. 도메인 논리는 moderator.EditPost ()와 같은 이러한 개체에서 구현됩니다. 거기
LittlePilgrim

나는 여전히 이것에 대한 답변 / 방향을 찾고 있지만 객체의 현재 상태 (예 : 중재자에게 할당 된 경우)에 의존하는 모든 권한 부여 논리는 실제로 비즈니스 논리에 속한다는 것을 알았습니다. 또한 도메인에 있지 않은 경우 모델을 동시에 업데이트 할 수있는 경우 유효하지 않은 상태가 될 위험이 있습니다. 예를 들어 정책을 사용하여 소유권을 확인한 다음 해당 개체를 업데이트하면 많은 도메인에서 소유권이 변경 될 수 있으며 작업이 더 이상 유효하지 않을 수 있습니다.
Jordan

매우 복잡한 협업 컨텍스트가 없으면 버전 관리를 사용하여 낙관적 동시성 모델을 구현할 수는 있지만 특정 집계 인스턴스 내에서 또는 적어도 특정 집계 인스턴스에 대해 확인을 수행하지 않으면 확인이 실제와 일치하지 않을 수 있습니다 변경 사항을 유지할 때까지 객체의 상태.
Jordan

5

인증 및 권한 부여는 DDD에 대한 나쁜 예입니다.

회사에서 보안 제품을 만들지 않는 한이 두 가지가 도메인의 일부가 아닙니다.

비즈니스 또는 도메인 요구 사항은 "역할 기반 인증이 필요합니다"여야합니다.

그런 다음 도메인 기능을 호출하기 전에 역할을 확인하십시오.

당신은 '나는 내 자신의 게시물을 편집 할 수 있지만 다른 사람이'당신의 도메인에 편집 기능을 분리되도록 복잡한 요구 사항이 어디 EditOwnPost()과를 EditOthersPost()그래서 당신은 역할 매핑에 대한 간단한 기능을 가지고

당신은 또한 다음과 같은 도메인 개체로 기능을 분리 할 수 Poster.EditPost()Moderator.EditPost()당신의 선택은 당신의 방법은 도메인 서비스 또는 도메인 개체에 있는지 여부에 따라 달라질 수 있지만이 좀 더 OOP 방식이다.

그러나 역할 매핑이 도메인 외부에서 발생하는 코드를 분리하도록 선택합니다. 예를 들어 webapi 컨트롤러가있는 경우 :

PostController : ApiController
{
    [Authorize(Roles = "User")]
    public void EditOwnPost(string postId, string newContent)
    {
        this.postDomainService.EditOwnPost(postId, string newContent);
    }

    [Authorize(Roles = "Moderator")]
    public void EditOtherPost(string postId, string newContent)
    {
        this.postDomainService.EditOtherPost(postId, string newContent);
    }
}

역할 맵핑이 호스팅 계층에서 수행 되더라도 자신 또는 다른 게시물을 편집하는 구성의 복잡한 논리 는 도메인의 일부입니다.

도메인은 조치의 차이점을 인식하지만 보안 요구 사항은 단순히 "기능이 역할에 의해 제한 될 수 있음" 입니다.

이것은 아마도 도메인 객체 분리와 함께 더 명확하지만 본질적으로 서비스 메소드를 호출하는 메소드 대신 객체를 구성하는 메소드를 확인하고 있습니다. 도메인의 일부로 여전히 음성을 보내려면 '중재자 만 중재자 개체를 구성 할 수 있습니다.'


4
"정적으로"역할을 점검하는 것은 약간 간단합니다. 중재자가 다른 중재자의 게시물을 편집 할 수 없으면 어떻게합니까? 이 검사가 도메인의 일부가 아니어야합니까?
Réda Housni Alaoui

2
@ RédaHousniAlaoui 나도 이것에 대해 궁금합니다. 도메인의 사용자 / 중재자에 대한 언급을 포함하거나 게시물의 작성자 역할을 얻기 위해 해당 ApiController 내에서 일종의 논리를 수행하는 것 이외의 다른 방법으로는 생각할 수 없습니다. 이것들 중 어느 것도 옳지 않은 것 같으며, 이것은 내 경험상 명확한 지침이 매우 도움이 될만한 일반적인 종류의 일입니다.
Jimmy

1
@ Erwan, 내가 이야기하는 유스 케이스는 역동적입니다. Hello World 예제에 대한 "인증 및 권한 부여는 DDD에 대한 나쁜 예"라는 문장을 기초로하여 부정직합니다. DDD는 우연한 복잡성을 피하고 도메인 복잡성을 관리 할 수 ​​있도록하기 위해 여기에 있습니다. 동적 권한은 우연히 복잡하거나 실생활에서는 일어나지 않는 것이 아닙니다.
Réda Housni Alaoui 2015 년

1
IMHO, 솔루션의 문제점은 고객을 만족시키지 못한다는 것입니다. 고객은 종종 이러한 관계를 동적으로 변경할 수 있기를 원합니다. 또한 공급 업체가 서로 다른 회사에 동일한 엔터프라이즈 소프트웨어를 제공 할 때도 마찬가지입니다. 소프트웨어를 조정할 수없는 경우 공급 업체는 결국 사망합니다.
Réda Housni Alaoui 2015 년

1
"하지만 일반적으로 보안 설정을 관리 할 수없는"나쁜 일 "로 인식되어 앱이 안전하지 않게됩니다." 올바른 설계 및 테스트를 통해 완전히 관리 할 수 ​​있습니다. 그러나 내 XP에서 올바른 디자인을 만들려면 도메인에서 권한을 확인해야합니다. 대안은 유토피아입니다.
Réda Housni Alaoui 2015 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.