2010-08-15 14 views
17

Estoy intentando descubrir cómo redirigir a un usuario a la página desde la que inició sesión (o no pudo iniciar sesión) usando Warden/Devise. Me imagino que hay una variable de sesión en algún lugar que está disponible o podría estar disponible.Rails: Warden/Devise: cómo capturar la url antes del inicio de sesión/acceso fallido

E.g. Escenario 1: El usuario no autorizado va a la página protegida X; Redirigido a la página de inicio de sesión; El usuario inicia sesión; Usuario redirigido a la página protegida x

Escenario 2: El usuario no autorizado desea realizar una acción protegida en la página x; El usuario hace clic en el enlace de inicio de sesión; El usuario inicia sesión; Usuario redirigido a la página x donde la acción está ahora disponible

Se agradecen todos los punteros.

Gracias!

Respuesta

1

Puede usar request.referer para obtener la URL anterior.

13

Hay un método de asistente de ayuda llamado after_sign_in_path_for(resource) (http://rdoc.info/github/plataformatec/devise/master/Devise/Controllers/Helpers), y una variable de sesión llamada session[:"user.return_to"] que almacena la última url. El método after_sign_in_path_for necesita devolver una cadena, luego idear utiliza automáticamente esta ruta para redirigir al usuario después de iniciar sesión.

En mi controlador de aplicación que han puesto lo siguiente, que vuelve a dirigir mis usuarios a la página de inicio si la variable de sesión no se ha establecido:

def after_sign_in_path_for(resource) 
    (session[:"user.return_to"].nil?) ? "/" : session[:"user.return_to"].to_s 
end 
+9

que tenía que usar 'sesión [: user_return_to]' como se ha mencionado en este SO responder: http://stackoverflow.com/a/5959018/337903 – Nick

+1

session [: user_return_to] funciona con esta solución, como Nick dijo –

+1

Una versión más concisa de esta respuesta (usando 'user_return_to' en lugar de' user.return_to'): sería 'session [: user_return_to] || root_path' – GMA

1

Si su uso CanCan de autorización se puede lograr esto se agregó la siguiente . De lo contrario, debería poder adaptar los conceptos a su sistema de autorización actual.

app/controllers/application_controller.rb

rescue_from CanCan::AccessDenied do |exception| 
    flash[:error] = exception.message 
    if user_signed_in? 
     redirect_to root_url 
    else 
     # Adds the protected page to the login url but only if the user is not logged in 
     redirect_to login_path(:next => request.path) 
    end 
    end 

    def after_sign_in_path_for(resource_or_scope) 
    # if a protected page found, then override the devise after login path 
    params[:user]["next"] || super 
    end 

app/views/diseñar/sesiones/new.html.erb

<% if params[:next] %> 
     <%= f.hidden_field :next, :value => params[:next] %> 
    <% end %> 

En lugar de utilizar variables de sesión Esta solución utiliza parametros en el URL para realizar un seguimiento de la página protegida.

+0

¿Alguna razón para no usar la sesión? ¿Es esto válido con la última versión de diseño? – justingordon

+0

Es posible que necesite agregar algo como esto: devise_scope: user do match '/ login' => 'users/sessions # new', como: "login" end or else rails se quejará de que login_path no se encuentra. Eso es con el último invento a partir del 25 de noviembre de 2012. – justingordon

0

esto es lo mejor que pude hacer. Funciona perfectamente también con la autenticación de Facebook. añadiendo más restricciones a la prepending de URLs a la variable de sesión puede eliminar más y más rutas no desea que el usuario vuelva demasiado (por ejemplo, devoluciones de llamada, páginas de bienvenida, páginas de destino, etc.)

#ApplicationsController 

after_filter :store_location 

def store_location 
    session[:previous_urls] ||= [] 
    # store unique urls only 
    session[:previous_urls].prepend request.fullpath if session[:previous_urls].first != request.fullpath && request.fullpath != "/user" && request.fullpath != "/user/login" && request.fullpath != "/" && request.fullpath != "/user/logout" && request.fullpath != "/user/join" && request.fullpath != "/user/auth/facebook/callback" 
    # For Rails < 3.2 
    # session[:previous_urls].unshift request.fullpath if session[:previous_urls].first != request.fullpath 
    session[:previous_urls].pop if session[:previous_urls].count > 3 
end 

def after_sign_in_path_for(resource) 
    @url = session[:previous_urls].reverse.first 
    if @url != nil 
    "http://www.google.com" + @url 
    else 
    root_path 
    end 
end 
1

Vaya, me acabo de dar cuenta de que devise (3.5.2) hace esto solo entre bastidores (alrededor de Devise::SessionsController#new acción), no se requieren modificaciones adicionales en el controlador.

Si necesita explícitamente store/get anterior location, por favor ver mi respuesta anterior:

Actualmente (Otoño 2015) hay una manera más atractiva para hacer eso:

Devise::Controllers::StoreLocation#store_location_for:

# Stores the provided location to redirect the user after signing in. 
# Useful in combination with the `stored_location_for` helper. 

store_location_for :user, dashboard_path 
redirect_to user_omniauth_authorize_path :facebook 

Devise::Controllers::StoreLocation#stored_location_for:

# Returns and delete (if it's navigational format) the url stored in the session for 
# the given scope. Useful for giving redirect backs after sign up: 

redirect_to stored_location_for(:user) || root_path 

Los métodos manejan relacionados session clave y el valor eliminación después de leer, todo lo que necesita es proporcionar su clave :resource (:user en el ejemplo anterior) y una ruta para almacenar (dashboard_path en el ejemplo anterior). Ver source para los detalles.

En cuanto a la respuesta real que va a ser algo así:

class ApplicationController < ActionController::Base 
    rescue_from CanCan::AccessDenied, with: :access_denied 

    # ... 

    private 

    def access_denied(exception) 
    store_location_for :user, request.path 
    redirect_to user_signed_in? ? root_path : new_user_session_path, alert: exception.message 
    end 

    def after_sign_in_path_for(resource) 
    stored_location_for(:user) || root_path 
    end 
end 
Cuestiones relacionadas