2011-01-09 16 views
12

Estoy tratando de usar skip_before_filter solo si la aplicación está en modo de producción. (No quiero que mis instancias de desarrollo sean públicas, y quiero que la aplicación detecte automáticamente en qué tipo de instancia está y muestre una pantalla de inicio de sesión cuando no esté en modo de producción). Por lo tanto, mi controlador de aplicación tiene la línea siguiente:skip_before_filter ignora condicionales

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

y el controlador de páginas que muestran tiene esta línea:

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

Y in_production es simplemente:

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

Soy consciente de que hay puede haber otras vías aquí, pero tengo curiosidad sobre por qué skip_before_filter parece ignorar el condicional y siempre omita el before_filter. ¿Se me escapa algo?

+0

Usando Rails 2.3.9 y la gema de autenticación Devise. – Smudge

Respuesta

17

Es un error de Rails (o al menos un comportamiento extraño no documentado). Se rastrea aquí: https://github.com/rails/rails/issues/9703

En este hilo, puede encontrar una solución (retorcida).

En lugar de

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

escritura

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

que trabajó para mí.

4

no estoy seguro skip_before_filter acepta un parámetro :if, por lo que me gustaría probar esta sintaxis

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

Si aún así no funciona, trate de poner esto en su controlador de aplicación

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

Ese primer ejemplo funciona. Si no acepta un: si param, ¿por qué es silencioso al respecto? – Smudge

+1

'skip_before_filter' toma un splat de matriz' * filters', por lo que no puede decir si hay argumentos inválidos. Me imagino que cuando se trata el splat, las claves hash no válidas se ignoran (o no se recuperan). –

6

He encontrado que la solución publicada por SmartLove en el escenario descrito presenta una especie de agujero de seguridad o un comportamiento inesperado. La línea

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

debido a la :only => :show, se anulando el vigente before_filter definido en el ApplicationController. Eso significa que todas las acciones de este controlador (por ejemplo: editar,: crear, etc.), excepto el: mostrar una, ¡omitirán al usuario autenticado! filtrar.

Una posible solución es eliminar la sola cláusula y verificar la acción llamada dentro del método condicional. Por ejemplo:

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

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