Java 限制对DDD中对象所有者的访问
假设有一个对象Java 限制对DDD中对象所有者的访问,java,security,domain-driven-design,authorization,Java,Security,Domain Driven Design,Authorization,假设有一个对象TaskList,它只能由其所有者编辑和删除。其他用户只能通过执行任务并更新其状态来完成任务 我想到了以下几种选择: 检查web应用程序控制器中的所有权和访问权 让存储库返回在某些操作上引发异常的代理对象,但控制器(或视图)仍需要知道哪些操作(以链接或表单字段的形式)应该可见 将调用者(用户)传递给域对象的方法,以便域对象本身可以检查调用者是否被允许 使用的技术是Java 还有其他/更好的主意吗 关于安全性和DDD的有趣文章 使用Spring框架 我现在接受了我自己的答案
TaskList
,它只能由其所有者编辑和删除。其他用户只能通过执行任务并更新其状态来完成任务
我想到了以下几种选择:
- 检查web应用程序控制器中的所有权和访问权
- 让存储库返回在某些操作上引发异常的代理对象,但控制器(或视图)仍需要知道哪些操作(以链接或表单字段的形式)应该可见
- 将调用者(用户)传递给域对象的方法,以便域对象本身可以检查调用者是否被允许
- 使用Spring框架
我现在接受了我自己的答案,因为这是我实际使用的答案,但欢迎进一步的建议 我不会将所有权/权限模型编码到
任务列表
域对象中。这种业务逻辑应该是外部的。我也不喜欢代理对象的概念。虽然它肯定会工作,但它会混淆调试,并且在本例中,至少是不必要的复杂。我也不会在控制器中检查它
相反,我将创建一个业务逻辑对象,用于监督TaskList
的权限。因此,TaskList
将有一个owner字段,但您将有如下内容:
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
对象上的所有操作都通过访问器进行,则可以创建一个factory类,该类是唯一使用包构造函数或其他方法创建TaskList
的类。也许工厂是唯一一个使用DAO从数据存储中查找任务列表的人
然而,如果有太多的方法以这种方式控制,那么代理可能更容易。在这两种情况下,建议使用
TaskList
作为接口,实现类由代理或访问器隐藏。我发现为每个受保护的域类创建访问器类(如“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);
}
}
公共类任务列表{
私有系统用户所有者;
私有列表任务=新建ArrayList();
公共用户列表(系统用户所有者){
this.owner=所有者;
}
公共作废添加(任务){
(业主)的保安许可证;
任务。添加(任务);
}
}
Guard
知道当前用户(例如从本地线程),并将其与作为参数传递给allowFor(owner)
的所有者进行比较。如果拒绝访问,将引发安全异常
这是一种简单、健壮甚至易于维护的方法,因为如果底层身份验证发生更改,则只需更改保护