【发布时间】:2025-11-24 22:25:01
【问题描述】:
我知道在 Rails 中制作了几个 gem 来处理授权。但是将这些 gem 用于简单的访问控制真的值得吗?
我的应用程序中只有几个“角色”,我觉得强大的gem毫无用处,甚至会拖慢响应时间。
我已经实现了一个解决方案,但后来我学习了一些安全类 (:p),我意识到我的模型是错误的(“默认允许,然后限制”而不是“默认拒绝,然后允许”)。
现在我怎样才能简单地实现“默认拒绝,在特定情况下允许”?
基本上我想放在我的 ApplicationController 的最顶部
class ApplicationController < ApplicationController::Base
before_filter :deny_access
在我的其他控制器的最顶端:
class some_controller < ApplicationController
before_filter :allow_access_to_[entity/user]
这些allow_access_to_ before_filters 应该执行类似skip_before_filter 的操作
def allow_access_to_[...]
skip_before_filter(:deny_access) if condition
end
但这不起作用,因为这些allow_access before 过滤器不会在deny_access before_filter 之前进行评估
对于这种访问控制的自定义实现有什么变通方法和更好的解决方案?
编辑
- 许多非 RESTful 操作
- 我需要按操作访问控制
-
undefined method 'skip_before_filter' for #<MyController...为什么? - 我的 before_filters 可能会变得很棘手
before_action :find_project, except: [:index, :new, :create]
before_action(except: [:show, :index, :new, :create]) do |c|
c.restrict_access_to_manager(@project.manager)
end
【问题讨论】:
-
过滤器按列出的顺序调用之前。但是您可以使用
prepend_before_filter代替allow_access_to_将其添加到前置过滤器堆栈的前面。 -
制作一个轻量级的 mixin 模块,它有一个名为
authorize(或其他名称)的方法。在 ApplicationController 级别添加此模块并调用authorize作为ApplicationController'sbefore_filter。让authorize的默认实现拒绝一切。在您的子控制器中,覆盖authorize以执行您想要的授权。基本上这只是一个简单的授权 gem 的 DIY 形式。 -
我需要按操作访问控制。所以我不能只在控制器中重新定义
authorize方法。或者,我必须在此方法中检查我正在调用哪个操作。 -
不过,您在使用通用过滤器方法时会遇到同样的问题。像
cancancan这样的东西解决了这个问题,但那是一个外部的宝石(相当轻巧,但仍然超出了您的问题范围)。但是,如果您遵循基本的 CRUD 模式,只需为每个 CRUD 字母分配方法,并且仅在您有奇怪的地方时才覆盖。然后在authorize中执行类似if :read, then类型的逻辑。同样,如果是混入,大多数子控制器的代码几乎看不到它。这使您无需测试每个操作,但可以让您轻松更改(与cancancan相同)。 -
使用过滤器方法,我可以做到
prepend_before_action :allow_access_to_, only: [:action1, :action2]
标签: ruby-on-rails ruby access-control