2011-08-31 88 views
22

我正在编写一个具有一些ACL要求的Web应用程序:用户可以对某些项目进行更改,某些项目可能由多个用户编辑,管理员可以编辑任何内容并且管理员可以编辑她的组织内的所有内容等。授权应该是模型还是控制器的一部分?

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

另一方面,向模型添加授权意味着我必须有某种方式从模型中获取当前用户,这似乎不正确。或者,我可以为每个模型方法添加一个“current_user”参数,但似乎更糟。

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

回答

14

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

我建议控制器逻辑绝对是控制对模型访问的正确位置,尤其是当它主要在注释级别进行管理时,并且认证被抽象为安全类。

+7

那么,它是灰色地带,还是绝对正确? :) – itsadok

+3

在我看来,我认为这是绝对正确的,但是,这是一个灰色地带,因此可以进行解释。那么,这取决于你是否同意我的解释:o) – Codemwnci

4

在大多数情况下,安全性应该是模型上方的一个(或更多)层。安全是它自己的一个域,限制对低层的访问。

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

在我看来,这应该是一个:

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

安全层可以是外观还是在模型的代理,保护访问,但对控制器透明。但是,如果要根据用户的访问权限修改视图,则可能必须在控制器级别进行一些检查(例如,在ViewModel上设置CanEdit布尔属性的值)。

+0

你在混合安全和授权。安全问题必须在应用程序的每个层面上处理 - 请参阅:纵深防御。问题是“授权属于哪里?”,而不是安全性。 –

1

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

相反,它应该在服务层。

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

假设用户A被授权访问来自域X的数据,但未被授权访问来自域Y的数据的读取访问。如果授权被放置在控制器中,则用户A在控制器X中获得授权,并且通过服务呼叫可以访问来自域Y的数据,这不是我们所期望的。

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

0

我在这个阶段,并打算通过以下方式来处理这个问题:

  • 没有形式通过JS验证,而不是通过HTTPS AJAX

  • 一个AJAX的PHP类

  • 表格数据发送到模型作为其数据的具体验证
    常见类型,如电子邮件和密码(可能assoc数组验证将被其他类重用,所以这是definat只是一个示范区)。

  • 如果没有错误在用户表中的凭据的查找电子邮件传递到与认证
    类型如登录/注册/口令的控制器/
    密码凭证重置

  • 控制器然后产生所需的输出视图或设置用户登录会话等

这是基于在Laravel,但我有自己的库作为希望它独立laravel的,只是松散的,基于此VITA l要求。

问题的关键在于模型将所需凭证作为数据查找,然后发送给Controller,因为它不关心应该如何处理它。我认为这是使这个领域成为每个组件之间的明确责任的唯一途径。

0

我与MVC框架个人的经验,我会说:

  1. 型号是代表数据库表中的对象应该是 纯粹,不应包含任何额外的逻辑。
  2. 控制器是做决定的地方和其他 定制逻辑,所以授权应该在控制器中。它可以设计一些钩子,可以检查用户是否被授权 或不在所有需要的地方,所以你不会有代码重复干。

  3. ,如果你使用的是典型的 REST架构给权限的用户,最好的办法是做一个标记,将其保存在DATABSE和 客户端,并验证在每次请求该令牌。如果您使用的是 网络浏览器应用程序,则可以使用服务器端会话进行授权( 更容易)。

所以我的建议是保持授权逻辑在控制器。

相关问题