基于领域驱动设计,如何管理聚合的权限访问?
基于DDD的B2B订单系统权限验证方案分析
场景背景
我们正在构建一套遵循**领域驱动设计(DDD)**的B2B订单管理系统,核心需求之一是为客户、订单、订单项分配专属的流程负责人,权限规则如下:
- 若用户被分配负责某客户,则拥有该客户所有订单的完整访问权限
- 若用户仅被分配负责某订单项,则仅能操作该订单项的相关业务
举个实际场景:宝马(BMW)采购轴承和紧固件,对应订单包含两个订单项。马克(Mark)负责宝马客户,因此他能操作整个订单;埃隆(Elon)负责轴承订单项,仅能对该订单项执行报价准备等操作。
领域模型核心代码示例:
public class Order { public CustomerId CustomerId { get; } private List<OrderItem> _items = []; // ... public void ChangeOrderHeader() // 仅Mark可执行 { // ... } }
public class OrderItem { public OrderId OrderId { get; } // ... public void PrepareOffer() // Mark可执行;若为轴承订单项,Elon也可执行 { // ... } }
核心问题
在上述场景下,如何在遵循DDD原则的前提下实现合理的权限验证管理?
现有方案分析
方案1:将权限验证作为领域方法内的业务规则
直接在领域对象的方法中传入用户信息并做权限校验:
public void PrepareOffer(User user) { EnsurePermissions(user); // 校验逻辑可封装为策略 // ... 业务逻辑 }
缺点:
- 需向聚合内所有方法传递用户/策略信息,代码冗余
- 违背DDD领域层核心原则:领域层应聚焦"做什么/怎么做",而非"谁来做",混入权限逻辑会污染领域模型
方案2:在仓储层保存时校验权限
在仓储的Save方法中,检查聚合是否被修改,再验证当前用户的操作权限:
public class Repository(IUserAccessor userAccessor) { public Task Save(Order order) { var user = userAccessor.GetCurrentUser(); if(order.WasModified()) { EnsureOrderPermissions(order, user); } // ... 保存逻辑 } }
优点:无代码冗余,无需修改领域模型
缺点:将权限这一业务逻辑转移到了基础设施层(仓储属于基础设施层),违背DDD分层职责,导致业务逻辑分散,难以维护
方案3:在应用层调用领域方法前校验权限
在应用服务中,先完成权限校验,再调用领域对象的方法:
public class OrderService(IUserAccessor userAccessor) { public void PrepareOffer(Order order, OrderLineId orderLineId) { var user = userAccessor.GetCurrentUser(); EnsureOrderLinePermissions(orderLineId, user); order.PrepareOrder(orderLineId); } }
优点:
- 符合DDD分层职责:应用层负责协调业务流程,包含"谁能做"的权限逻辑,领域层专注核心业务
- 权限逻辑集中,易于维护和扩展
缺点:代码量略高于方案2,需为每个领域操作对应编写应用层的校验逻辑
方案4:在端点授权层执行资源特定授权
直接在API端点层实现针对订单/订单项的细粒度授权逻辑。
优点:权限校验前置,避免无效的领域层调用
缺点:实现复杂度高,尤其是需要结合订单/订单项的业务属性(如客户负责人、订单项负责人)做动态授权时,容易在端点层混入业务规则,导致代码难以维护
推荐方案
优先选择方案3,理由如下:
- 严格遵循DDD分层职责:应用层承接"谁能执行操作"的权限逻辑,领域层纯粹处理核心业务规则,边界清晰
- 权限逻辑集中在应用层,便于统一维护和调整,比如后续新增权限规则时,无需修改领域模型
- 可结合策略模式封装权限校验逻辑,减少代码冗余:例如将
EnsureOrderLinePermissions、EnsureOrderHeaderPermissions等封装为可复用的权限策略类,在应用层注入使用
如果追求更极致的权限前置校验,可在方案3的基础上,结合端点层的基础授权(如登录校验、角色校验),再由应用层完成细粒度的资源权限校验,兼顾安全性和分层合理性。
内容的提问来源于stack exchange,提问作者GeorgeKarlinzer
相关产品推荐
相关产品推荐

