授权是否应该是模型或控制器的一部分?

its*_*dok 25 model-view-controller authorization playframework

我正在编写一个具有一些ACL要求的Web应用程序:用户可以更改某些项目,某些项目可以由多个用户编辑,管理员可以编辑任何内容,管理员可以编辑组织内的所有内容等.

我正在使用Play!框架,以及Secure模块的外观,似乎放置授权问题的地方在控制器中.但是,在我看来,授权问题是业务逻辑的一部分,因此应该在模型中.此外,我开始看到控制器中需要重构的重复逻辑.

另一方面,向模型添加授权意味着我必须有一些方法从模型中获取当前用户,这似乎不对.或者,我可以为每个模型方法添加"current_user"参数,但这看起来更糟.

那么常见的做法是什么?可以/应该将授权代码放在模型中,还是将其保存在控制器中?

Cod*_*nci 16

我认为这是一个灰色地带.有人可能会争辩说,用户访问是HTTP世界和面向对象世界之间映射的一部分.这是控制器的目的(因此大量使用静态),转换传入的请求,准备处理域模型上的业务规则.

我建议控制器逻辑绝对是控制模型访问的正确位置,特别是因为这主要是在注释级别进行管理,并且身份验证被抽象为Security类.

  • 那么它是灰色区域,还是绝对正确?:) (7认同)
  • 在我看来,我认为这是绝对正确的,但是,它是一个灰色区域,因此可以解释.那么,这取决于你是否同意我的解释:o) (4认同)

小智 12

授权不应成为控制器或域模型的一部分。

相反,它应该在服务层。

控制器应该只充当 HTTP 和应用程序服务之间的调度程序和委托。它是进行编排的应用程序服务。这是放置授权的最佳位置。

假设用户 A 被授权访问来自域 X 的数据,但没有被授权对来自域 Y 的数据进行读取访问。如果授权被放置在控制器中,那么用户 A 在控制器 X 中获得授权,并且通过服务调用可以从域 Y 访问数据,这不是我们所期望的。

由于领域模型在服务层相互通信,因此最好将授权放在同一级别。

  • 另一个副作用,控制器可能不是服务的唯一入口点,如果我突然想要 gRPC 端点 & 1 gRPC 端点将所有内容映射到服务,与 websockets 相同,控制器应该只将请求转换为域对象,一次它在内部传递,服务负责处理一切,这样您就可以在需要时升级端点。 (2认同)

Mar*_*tin 6

在大多数情况下,安全性应该在模型之上一层(或多层)。安全本身就是一个域,它限制了对较低层的访问。

我认为安全性不应在控制器级别上完成。

我认为这应该像这样:

查看->控制器->安全->模型

安全层可以是模型的外观或代理,以保护访问,但对控制器透明。

但是,如果要根据用户的访问权限来修改视图,则可能必须在控制器级别进行某些检查(例如,在ViewModel上设置CanEdit布尔属性的值)。