假设我有一个调用存储库层的 ASP.NET MVC Web 应用程序,该存储库层构建在 nHibernate 之上。控制器传递一个ISecurityToken
封装当前用户身份和权限的存储库,存储库在查询时使用它只返回用户应该能够看到的行。
我希望实体(票证)只能由特定的用户组以及票证分配给的用户关闭。换句话说,假设CanCloseTicket()
方法需要两个输入:
- 票证本身(或其当前所有者 ID)
- 当前用户的
ISecurityToken
这种假设的方法应该在哪里?我可以看到几种可能性,但每种都有其缺点。
- 在控制器中:控制器可以访问所有必要的东西,但这使得安全性被绕过成为可能。(“糟糕,在设置为 false 之前,我忘记在此操作中调用 CanCloseTicket()
ticket.IsOpen
!”这闻起来很糟糕。 - 在存储库中:存储库也可以访问这两个部分,但我还必须将
Ticket.IsClosed
's setter 设为私有以阻止上述相同事情的发生。存储库位于与模型完全不同的程序集中,因此使用内部设置器将不起作用。相反,我可以将 setter 公开并将属性的当前值与其原始值进行比较,如果非特权用户将其关闭,则返回错误,但这对我来说也有点奇怪。(“糟糕,我忘记检查repo.CloseTicket()
这个动作方法的返回值了!”) - 在票证中:添加
Ticket.Close(ISecurityToken token)
并让实体负责自己的安全逻辑感觉就像违反了SRP。
我认为存储库是这里最好的选择,但感觉更像是最差的选择。还有别的事吗?