2011-01-09 105 views
12

我只在应用程序处于生产模式时才试图使用skip_before_filter。 (我不希望公开我的开发实例,我希望应用程序自动检测它的实例类型,并在未处于生产模式时显示登录屏幕)。所以,我的应用程序控制器具有以下行:skip_before_filter忽略条件

before_filter :authenticate_user!, :except => "sign_in" #redirects to log-in 

而控制器用于显示网页有这一行:

skip_before_filter :authenticate_user!, :only => :show, :if => :in_production 
#public pages are public, but only when in production. 

而且in_production很简单:

def in_production 
    ENV['RAILS_ENV']=='production' 
    end 

我认识到,有可能是其他途径这里,但我很好奇,为什么skip_before_filter似乎忽视了条件和永远只是跳过的before_filter。有什么我失踪?

+0

使用Rails 2.3.9和Devise身份验证gem。 – Smudge 2011-01-09 01:03:27

回答

17

这是一个Rails错误(或者至少是一个无证的奇怪行为)。它被追踪到这里:https://github.com/rails/rails/issues/9703

在这个线程中,你可以找到一个(扭曲的)解决方案。取而代之的

skip_before_filter :authenticate_user!, :only => :show, :if => :in_production 

skip_before_filter :authenticate_user!, :only => :show 
before_filter  :authenticate_user!, :only => :show, :unless => :in_production 

它为我工作。

4

我不知道skip_before_filter接受一个:if参数,所以我想尝试这句法

(skip_before_filter :authenticate_user!, :only => [:show]) if in_production 

如果还是不行,请尝试把这个应用程序中的控制器

if ENV['RAILS_ENV']=='production' 
    skip_before_filter :authenticate_user!, :only => :show 
end 
+0

第一个例子有效。如果它不接受:如果参数,它为什么对此保持沉默? – Smudge 2011-01-09 01:35:29

6

我发现SmartLove在上述场景中发布的解决方案存在一种安全漏洞或意外行为。行

before_filter :authenticate_user!, :only => :show, :unless => :in_production

因为:only => :show的,被覆盖现有的before_filter在ApplicationController中所定义。这意味着除了:show one之外,此控制器的所有操作(例如:edit,:create等)都将省略authenticate_user!过滤。

一种可能的解决方案是去除:仅子句和检查称为条件方法内的动作。例如:

before_filter :authenticate_user!, :unless => :skip_filter? 

def skip_filter? 
    params[:action] == "show" && in_production 
end