假设我有一个 ASP.NET MVC Web 应用程序,它调用存储库层,该层构建在 nHibernate 之上。控制器将存储库传递给 ISecurityToken 它封装了当前用户的身份和权限,并且存储库在查询时使用它以仅返回用户应该能够看到的行。

我希望实体(票证)只能由特定用户组以及票证分配给的用户关闭。换句话说,假设的 CanCloseTicket() 方法需要两个输入:

  1. 门票本身(或其当前所有者 ID)
  2. 当前用户的 ISecurityToken

这个假设的方法应该放在哪里?我可以看到几种可能性,但每种都有其缺点。

  • 在控制器中:控制器可以访问所有必要的内容,但这使得安全性有可能被绕过。(“哎呀,我忘记在设置之前在此操作中调用 CanCloseTicket() ticket.IsOpen 假的!”这闻起来很糟糕。
  • 在存储库中:存储库也可以访问这两个部分,但我还必须 Ticket.IsClosed的 setter 为私有,以阻止上述相同的事情发生。存储库位于与模型完全不同的组件中,因此使用内部设置器不起作用。相反,我可以将 setter 保留为公开,并将属性的当前值与其原始值进行比较,如果非特权用户关闭它,则返回错误,但这对我来说也有点不对劲。(“哎呀,我忘了检查返回值 repo.CloseTicket() 在这个动作方法中!”)
  • 门票中:添加 Ticket.Close(ISecurityToken token) 让实体负责自己的安全逻辑感觉像是违反了 建议零售价.

我认为存储库是这里最好的选择,但它 感觉 更像是最不坏的选择。还有别的事吗?

有帮助吗?

解决方案

你的最终选择对我来说听起来完全正确:当有人想要关闭票证时,他们必须提供 证据 以安全令牌的形式。(话虽如此,当您可以访问类的源代码时,判断是否违反 SRP 已经很困难了,我不能说我完全有信心。)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top