限制对 DDD 中对象所有者的访问

问题描述 投票:0回答:2

假设有一个对象

TaskList
,只能由其所有者编辑和删除。其他用户只能接受任务并更新其状态。

我想到了以下选项:

  • 检查 Web 应用程序控制器中的所有权和访问权限
  • 让存储库返回代理对象,该对象在某些操作上引发异常,但控制器(或视图)仍然需要知道哪些操作(以链接或表单字段的形式)应该可见
  • 将调用者(用户)传递给域对象的方法,以便域对象可以自行检查调用者是否被允许。

使用的技术是Java。

还有其他/更好的想法吗?

有关安全和 DDD 的有趣文章

我现在已经接受了我自己的答案,因为那是我实际使用的,但欢迎进一步的建议。

java security domain-driven-design authorization
2个回答
3
投票
我不会将所有权/权限模型编码到

TaskList

 域对象中。这种业务逻辑应该是外部的。我也不喜欢代理对象的想法。虽然它肯定会起作用,但它会混淆调试,并且至少在这种情况下会变得不必要的复杂。我也不会在控制器中检查它。

相反,我会创建一个业务逻辑对象来监督

TaskList

 的权限。因此 
TaskList
 将有一个所有者字段,但您将在外部访问器中拥有执行业务逻辑的功能。比如:

public class TaskListAccessor { private TaskList taskList; private User reader; public void updateStatus(Status status) { // everyone can do this taskList.updateStatus(status); } /** Return true if delete operation is allowed else false */ public boolean isDeleteAllowed() { return taskList.getOwner().equals(reader); } /** Delete the task. Only owners can do this. Returns true if worked else false */ public boolean delete() { if (isDeleteAllowed()) { taskList.delete(); return true; } else { return false; } } // ... other accessors with other is*Allowed methods }
如果您需要要求对 

TaskList

 对象的所有操作都通过访问器,那么您可以创建一个工厂类,它是唯一使用包构造函数或其他方法创建 
TaskList
 的类。也许工厂是唯一会使用 DAO 从数据存储中查找 
TaskList
 的工厂。

但是,如果以这种方式控制的方法太多,那么代理可能会更容易。在这两种情况下,都建议将

TaskList

 设为接口,并通过代理或访问器隐藏实现类。


0
投票
我发现按照“Gray”的建议为每个受保护域类创建访问器类不必要地复杂。我的解决方案可能并不完美,但使用简单,而且更重要的是健壮。你不能忘记使用某个物体或检查外面的情况。

public class TaskList { private SystemUser owner; private List<Task> tasks = new ArrayList<>(); public TastList(SystemUser owner) { this.owner = owner; } public void Add(Task task) { Guard.allowFor(owner); tasks.add(task); } }

Guard

知道当前用户(例如来自本地线程)并将其与作为参数传递给
allowFor(owner)
的所有者进行比较。如果访问被拒绝,将引发安全异常。

这简单、健壮,甚至易于维护,因为如果底层身份验证发生变化,只需更改防护。

© www.soinside.com 2019 - 2024. All rights reserved.