【问题标题】:Multi-tenant Rails app and restricting access to controllers多租户 Rails 应用程序和限制对控制器的访问
【发布时间】:2018-09-18 18:19:33
【问题描述】:

我正在使用 Devise 进行身份验证,并且我的 rails 应用程序中有“模块”。我正在尝试找出最佳的安全方法。例如,以下是我想要完成的几件事:

  • 我希望应用程序控制器要求登录,除非他们正在访问 registrations 控制器,在这种情况下他们只是提交注册详细信息。
  • 在应用程序级别,我想定义范围,允许访问用户公司有权访问的某些控制器。
  • 此外,对于每个请求,我想验证 URL 中的任何 ID(无论是 GET、POST 还是其他),用户的公司都可以访问该控制器和参数中的 ID。 (因此,如果他们的公司没有关联的报告 ID 9,他们就无法访问报告 ID 9)

我觉得这可能是可扩展的,但我以前从未这样做过,所以我不太确定。

子弹 1

在 ApplicationController 中,我想做这样的事情:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :authenticate_user! unless controller == "Registrations"
end

我尝试在应用程序控制器中放置binding.pry,但controller_path 似乎总是application。不确定是否有一种简单的方法可以在不使用每个单独的控制器的情况下完成此操作,我希望避免这种情况,因为我不想在添加新控制器时意外忘记某些东西(基本上与 DRY 相悖)。

也许我可以实现一个安全控制器并让每个控制器都继承它?以前从未这样做过,但如果我无法在应用程序控制器中完成我想要做的事情,这可能会起作用。

子弹 2

我尝试从应用程序控制器访问 Devise 的 current_user 变量,但它不存在,所以我不确定是否可以从应用程序控制器检查用户的权限。同样,我希望避免在每个控制器中都放置此检查,因为随着应用程序的扩展,我最终可能会忘记实施检查。

编辑

所以看起来我已经解决了项目符号 1,但现在我正试图找出其他 2。能够在应用程序级别实现某种类型的“范围”或权限模块。有什么想法吗?

【问题讨论】:

  • before_action ... unless cond 之类的代码存在很大问题。 unless 条件仅在控制器代码本身被加载时评估一次,而不是每次控制器运行时。你需要skip_before_action 来处理这种事情。
  • 知道了,所以在这种特殊情况下,听起来我只需要在每个新创建的控制器上手动实现before_action :authenticate_user!only 选项似乎只适用于操作,我想限制所有控制器上的所有操作,除非它是注册控制器。

标签: ruby-on-rails devise


【解决方案1】:

skip_before_action 指令可以禁止执行已定义的before_action 过滤器。您可以使用它来关闭控制器的操作:

class ApplicationController < ActionController::Base
  before_action :authenticate_user!
end

class RegistrationsController < ApplicationController
  skip_before_action :authenticate_user!
end

这里要注意的是 Ruby 是一种高度动态的编程语言,代码可以在定义类时执行。密切注意某些语句的运行时间非常重要,因为像 unless 这样的语句往往在这种情况下立即运行。

您会看到其他一些允许延迟执行的方法,例如在 ActiveRecord 中:

validates :name, unless: :anonymous?

validates 方法有一个名为unless 的特定选项,它与关键字unless 不同。这定义了一个附加条件的验证触发器。

另一方面,这段代码虽然看起来很相似,但完全不同:

validates :name unless anonymous?

这取决于在类级别可用的名为 anonymous? 的方法,如果它返回非 nilfalse 值,则将执行 validates 函数。

【讨论】:

  • 明白了。很重要的一点,感谢您提供此信息。这将使我能够完成我的目标的“需要经过身份验证的用户,除非他们正在访问注册控制器”部分。
  • 要求注册是一种相当常见的模式,当然,除非您首先尝试注册某人。作为一个注释,您可能想要创建一个RegistrationRequiredController 基类,该基类需要向该before_action 注册,并从该基类继承,而不是为所有需要注册的控制器。您可能需要其他可供非注册用户使用的控制器,因此值得考虑这种方法。缺点是您需要保持警惕才能正确继承,否则您的控制器将不会受到适当的限制。
  • 明白了。说得通。我也注意到了这一点,以防万一我确实需要另一个控制器可用。我真的很感激!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-06
  • 1970-01-01
  • 2018-08-29
  • 2012-12-27
  • 1970-01-01
  • 2011-06-08
相关资源
最近更新 更多