领域驱动设计中的访问控制 [英] Access Control in Domain Driven Design

查看:22
本文介绍了领域驱动设计中的访问控制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了关于 DDD 和访问控制的文章,发现以下两种观点有些矛盾:

I read about DDD and Access Control, and I found some contradiction between the following two opinions:

  • 安全问题应在域外处理"
  • 访问控制要求是特定于域的"

我正在寻找有关此的最佳实践.那么域驱动设计的访问控制逻辑应该放在哪里,又应该如何实现呢?

I am looking for a best practice about this. So where should I put the access control logic by domain driven design, and how should I implement it?

(通过 DDD + CQRS + ES 更具体.)

(To be more specific by DDD + CQRS + ES.)

我认为它应该靠近业务逻辑,例如用户故事可能是这样的:

I think it should be somewhere near to the business logic, for example a user story could be something like this:

用户可以通过发送用户名、爱好列表、简历等来编辑他的个人资料...

The user can edit his profile by sending an user name, a list of hobbies, cv, etc...

基于用户故事,我们实施领域模型和服务,例如:

Based on the user story we implement the domain model and the services, for example:

UserService
    editProfile(EditUserProfileCommand command)
        User user = userRepository.getOneById(command.id)
        user.changeName(command.name)
        user.changeHobbies(command.hobbies)
        user.changeCV(command.cv)

UserRepository
    User getOneById(id)

User
    changeName(String name)
    changeHobbies(String[] hobbies)
    changeCV(String cv)

没关系,但是故事的 HIS profile 部分在哪里?

This is okay, but where is the HIS profile part of the story?

这显然是基于属性的访问控制,因为我们应该写一个这样的规则:

This is obviously attribute based access control, because we should write a rule something like this:

deny all, but if subject.id = resource.owner.id then grant access

但是我们应该在哪里执行这个规则,我们应该如何实施它?

But where should we enforce this rule, and how should we implement it?

推荐答案

那么我应该把访问控制逻辑放在哪里?

So where should I put the access control logic?

根据此:https://softwareengineering.stackexchange.com/a/71883/65755 政策执行点应该在 UserService.editProfile() 调用之前.

According to this: https://softwareengineering.stackexchange.com/a/71883/65755 the policy enforcement point should be right before the call of the UserService.editProfile().

我得出了同样的结论:它不能在 UI 中,因为在多个 UI 中我们会有代码重复.应该在创建领域事件之前,因为它们表明我们已经在系统中做了一些事情.因此,我们可以限制对域对象或使用这些域对象的服务的访问.通过 CQRS,我们不需要读取模型的域对象,只有服务,所以如果我们想要一个通用的解决方案,我们必须限制对服务的访问.我们可以将访问决策放在每个服务操作的开始,但这将是 grant all, deny x 安全反模式.

I came to the same conclusion: it cannot be in the UI because by multiple UIs we would have code repetition. It should be before the creation of domain events, because they indicated that we have already done something in the system. So we can restrict the access to domain objects or to services which use those domain objects. By CQRS we don't necessary have domain objects by the read model, just services, so we have to restrict access to the services if we want a general solution. We could put the access decisions at the beginning of every service operation, but that would be grant all, deny x security anti pattern.

我应该如何实施?

这取决于哪种访问控制模型适合域,因此它取决于用户故事.通过访问决策,我们通常会发送访问请求并等待许可作为回报.访问请求通常有以下几个部分:主体、资源、操作、环境.因此,主体需要权限才能对环境中的资源执行操作.首先我们识别主题,然后我们对其进行身份验证,然后是授权,在这里我们检查访问请求是否符合我们的访问策略.每个访问控制模型都以类似的方式工作.办公室他们可能缺少其中一些步骤,但这并不重要......

This depends on which access control model fits to the domain, so it depends on the user story. By an access decision we usually send an access request and wait a permission in return. The access request usually has the following parts: subject, resource, operation, environment. So the subject requires permission to perform an operation on the resource in an environment. First we identify the subject, then we authenticate it, and after that comes the authorization, where we check whether the access request fits to our access policy. Every access control model works in a similar way. Ofc. they can lack of some of these steps, but that does not matter...

我创建了一个访问控制模型的简短列表.我将规则、策略放入注释中,但如果我们想要一个易于维护的系统,通常我们应该将它们存储在数据库中,可能以 XACML 格式......

I created a short list of access control models. I put the rules, policies into annotations, but normally we should store them in a database probably in XACML format if we want to have a well maintainable system...

  • 通过基于身份的访问控制 (IBAC),我们有一个身份 - 权限存储(访问控制列表、能力列表、访问控制矩阵).因此,例如通过访问控制列表,我们存储可以拥有权限的用户或组的列表.

  • By identity based access control (IBAC) we have an identity - permission storage (access control list, capability list, access control matrix). So for example by an access control list, we store the list of the users or groups whose can have permissions.

UserService
    @AccessControlList[inf3rno]
    editProfile(EditUserProfileCommand command)

  • 通过基于格的访问控制 (LBAC),主体具有许可级别,资源具有所需的许可级别,我们检查哪个级别更高...

  • By lattice based access control (LBAC) the subject has a clearance level, the resource has a required clearance level, and we check which level is higher...

    @posseses[level=5]
    inf3rno
    
    UserService
        @requires(level>=3)
        editProfile(EditUserProfileCommand command)
    

  • 通过基于角色的访问控制 (RBAC),我们定义了主体角色,并向扮演实际角色的主体授予权限.

  • By role based access control (RBAC) we define subject roles and we grant permissions to subjects whose act the actual role.

    @roles[admin]
    inf3rno
    
    UserService
        @requires(role=admin)
        editProfile(EditUserProfileCommand command)
    

  • 通过基于属性的访问控制 (ABAC),我们定义主题、资源和环境属性,并根据它们编写我们的策略.

  • By attribute based access control (ABAC) we define subject, resource and environment attributes and we write our policies based on them.

    @attributes[roles=[admin]]
    inf3rno
    
    UserService
        @policy(subject.role=admin or resource.owner.id = subject.id)
        editProfile(EditUserProfileCommand command)
        @attribute(owner)
        Subject getOwner(EditUserProfileCommand command)
    

  • 通过基于策略的访问控制 (PBAC),我们不会将我们的策略分配给其他任何东西,它们是独立的.

  • By policy based access control (PBAC) we don't assign our policies to anything else, they are standalone.

    @attributes[roles=[admin]]
    inf3rno
    
    UserService
        editProfile(EditUserProfileCommand command)
        deleteProfile(DeleteUserProfileCommand command)
        @attribute(owner)
        Subject getOwner(EditUserProfileCommand command)
    
    @permission(UserService.editProfile, UserService.deleteProfile)
    @criteria(subject.role=admin or resource.owner.id = subject.id)
    WriteUserServicePolicy
    

  • 通过风险自适应访问控制 (RAdAC),我们根据主体的相对风险状况和操作的风险级别做出决定.这不能用我认为的规则来描述.我不确定实现,也许这就是 stackoverflow 使用的点系统.

  • By risk-adaptive access control (RAdAC) we base our decision on the relative risk profile of the subject and the risk level of the operation. This cannot be described with rules I think. I am unsure of the implementation, maybe this is what stackoverflow uses by its point system.

    通过基于授权的访问控制 (ZBAC),我们不进行身份识别和身份验证,而是为身份识别因素分配权限.例如,如果有人发送令牌,那么她就可以访问服务.其他一切都类似于以前的解决方案.例如使用 ABAC:

    By authorization based access control (ZBAC) we don't do identification and authentication, instead we assign permissions to identification factors. For example if somebody sends a token, then she can have access to a service. Everything else is similar to the previous solutions. For example with ABAC:

    @attributes[roles=[editor]]
    token:2683fraicfv8a2zuisbkcaac
    
    ArticleService
        @policy(subject.role=editor)
        editArticle(EditArticleCommand command)
    

    所以每个知道 2683fraicfv8a2zuisbkcaac 令牌的人都可以使用该服务.

    So everybody who knows the 2683fraicfv8a2zuisbkcaac token can use the service.

    等等...

    还有许多其他型号,最适合的型号始终取决于您客户的需求.

    There are many other models, and the best fit always depends on the needs of your customer.

    总结一下

    - "security concerns should be handled outside the domain"
    - "access control requirements are domain specific"
    

    两者都可以,因为安全性不是域模型的一部分,但其实现取决于域模型和应用程序逻辑.

    both can be right, because security is not part of the domain model, but its implementation depends on the domain model and the application logic.

    两年后编辑2016-09-05

    自从我作为 DDD 新手回答我自己的问题以来,我已经阅读了 实施领域驱动设计 来自 Vaughn Vernon.这是一本关于这个主题的有趣的书.这是它的引述:

    Since I answered my own question as a DDD newbie, I have read Implementing Domain-Driven Design from Vaughn Vernon. It was an interesting book in the topic. Here is a quote from it:

    这构成了一个新的有界上下文——身份和访问上下文 - 并将通过标准被其他有界上下文使用DDD 集成技术.对于消费上下文,身份和访问上下文是一个通用子域.该产品将被命名IdOvation.

    This constitutes a new Bounded Context - the Identity and Access Context - and will be used by other Bounded Contexts through standard DDD integration techniques. To the consuming contexts the Identity and Access Context is a Generic Subdomain. The product will be named IdOvation.

    因此,根据 Vernon 的说法,可能是将访问控制移动到通用子域的最佳解决方案.

    So according to Vernon probably the best solution to move the access control to a generic subdomain.

    这篇关于领域驱动设计中的访问控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆