访问控制领域驱动设计


31

我了解DDD和访问控制,我发现了以下两种意见之间的一些矛盾:

  • “访问控制“安全关切应域之外处理”要求是域特定的“

我正在寻找这方面的最佳实践。那么我应该在哪里设置域驱动设计的访问控制逻辑,我应该如何实现它?

(要由DDD + CQRS + ES更具体的。)

我觉得应该是在业务逻辑的地方,例如用户故事可能是这样的:

用户可以通过发送用户名,爱好,品种等的列表编辑他的个人资料...

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

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这个故事的部分在哪里?

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

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

但是,我们应该在哪里执行这一规则,我们应该如何实现呢?

  0

在命令('command.id')中包含用户标识会引入歧义。更好地从命令中删除用户标识,并将授权上下文中的用户与命令一起传递。 21 2月. 162016-02-21 13:32:17

25

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

根据此:https://softwareengineering.stackexchange.com/a/71883/65755策略执行点应在UserService.editProfile()的呼叫之前。

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

我该如何实现它?

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

我创建了一个访问控制模型的简短列表。我把规则,政策纳入注解,但通常我们应该把它们存储在大概在XACML格式的数据库,如果我们希望有一个良好维护的系统...

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

    UserService 
        @AccessControlList[inf3rno] 
        editProfile(EditUserProfileCommand command) 
    
  • 通过晶格的访问控制(LBAC)的对象具有许可级别,资源都需要有一个间隙水平,我们检查其水平越高...

    @posseses[level=5] 
    inf3rno 
    
    UserService 
        @requires(level>=3) 
        editProfile(EditUserProfileCommand command) 
    
  • 通过基于角色的访问控制(RBAC)我们定义主体角色,并且我们授予其行为实际角色的主体权限。

    @roles[admin] 
    inf3rno 
    
    UserService 
        @requires(role=admin) 
        editProfile(EditUserProfileCommand command) 
    
  • 通过基于属性的访问控制(ABAC)我们定义主题,资源,环境的属性和我们基于他们写我们的政策。

    @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),我们不分配我们的政策,别的,他们是独立的。

    @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。

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

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

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

等等...

还有许多其他的模式,最适合总是取决于客户的需求。

所以总结

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

既可以是正确的,因为安全是不是域模型的一部分,但它的实现依赖于域模型和应用程序逻辑。 2年后 2016年9月5日

因为我回答我自己的问题作为一个新手,DDD

编辑,我从沃恩弗农读Implementing Domain-Driven Design。这是一本有趣的书。下面是它报价:

这构成了新的界上下文 - 身份和访问 语境 - 并且将被其它的限界上下文通过标准 DDD集成技术一起使用。对于使用上下文,身份和访问上下文是通用子域。该产品将被命名为 IdOvation。

所以根据弗农可能是最佳的解决方案将访问控制移动到一个通用的子域。

  0

关于编辑,很容易将基于角色,ACL或基于权限的移动到通用BC,但不是基于规则的授权。 15 8月. 172017-08-15 16:43:40