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

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

问题描述

我阅读了有关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配置文件在哪里是故事的一部分?

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 策略执行点应该在<$ c调用之前$ c> 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,我们不需要通过读取模型来拥有域对象,而仅需要服务,因此,如果我们想要一个通用的解决方案,就必须限制对服务的访问。我们可以将访问决策放在每个服务操作的开始,但这将是授予所有,拒绝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.


我应该如何实现?

How should I implement it?

这取决于适合哪种访问控制模型域,因此取决于用户故事。根据访问决策,我们通常会发送访问请求并等待获得许可。访问请求通常包括以下部分:主题,资源,操作,环境。因此,主题需要权限才能在环境中对资源执行操作。首先,我们确定主题,然后对它进行身份验证,然后是授权,然后在授权中检查访问请求是否符合我们的访问策略。每个访问控制模型的工作方式都相似。 Ofc。他们可以缺少某些步骤,但这没关系...

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

    edit after 2 years 2016-09-05

    由于我以DDD ne回答了自己的问题,我已经阅读了实现域驱动设计沃恩·弗农。这是一本有趣的书。

    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.

    因此,根据弗农看来,将访问控制转移到通用控件的最佳解决方案子域。

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

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

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