我需要在Ruby on Rails应用程序中实现细粒度的访问控制。单个用户的权限保存在数据库表中,我认为最好让相应的资源(即模型的实例)决定是否允许某个用户对其进行读写操作。每次在控制器中做这个决定肯定不会很枯燥。
问题是,为了做到这一点,模型需要访问当前用户,以调用类似于may_read?(current_user, attribute_name)
的东西。不过,模型通常不能访问会话数据。
在当前线程中保存对当前用户的引用有很多建议,例如在this blog post中。这肯定会解决这个问题。
相邻的Google results建议我在user类中保存对当前用户的引用,我猜这是某个应用程序不必同时容纳大量用户的人想出来的。;)
长话短说,我有一种感觉,我希望从模型中访问当前用户(即会话数据)的愿望来自我的doing it wrong。
你能告诉我我哪里错了吗?
发布于 2009-10-15 19:35:55
我要说的是,您将current_user
排除在模型之外的直觉是正确的。
像Daniel一样,我完全支持瘦控制器和胖模型,但也有明确的职责划分。控制器的用途是管理传入的请求和会话。该模型应该能够回答“用户x可以对此对象执行y操作吗?”这个问题,但是它引用current_user
是没有意义的。如果您是在控制台中,该怎么办?如果这是一个cron作业运行怎么办?
在许多情况下,在模型中使用正确的权限API,这可以通过应用于多个操作的一行before_filters
来处理。但是,如果事情变得越来越复杂,您可能希望实现一个单独的层(可能在lib/
中)来封装更复杂的授权逻辑,以防止您的控制器变得臃肿,并防止您的模型变得与web请求/响应周期耦合得太紧密。
发布于 2009-11-04 05:52:33
尽管这个问题已经得到了很多人的回答,但我只想快速补充一下我的两点意见。
由于线程安全的原因,在用户模型上使用#current_user方法应该小心实现。
如果您记得使用Thread.current作为一种方式或存储和检索值,那么在User上使用类/单例方法是很好的。但这并不那么简单,因为您还必须重置Thread.current,这样下一个请求就不会继承它不应该继承的权限。
我想说的是,如果您将状态存储在类或单例变量中,请记住您是在抛出线程安全性。
发布于 2012-11-30 21:57:00
控制器应该告诉模型实例
使用数据库是模型的工作。处理web请求,包括了解当前请求的用户,是控制器的工作。
因此,如果模型实例需要知道当前用户,控制器应该告诉它。
def create
@item = Item.new
@item.current_user = current_user # or whatever your controller method is
...
end
这里假设Item
有一个用于current_user
的attr_accessor
。
(注意-我首先在another question,上发布了这个答案,但我刚刚注意到这个问题是这个问题的副本。)
https://stackoverflow.com/questions/1568218
复制相似问题