2009-03-18 14 views
9

tengo instalado en una aplicación de rieles el plugin restful_authentication, con un sessions_controller que tiene un método de destruir de esta manera:Salir con la autenticación básica HTTP y el plugin restful_authentication

def destroy 
    self.current_user.forget_me if logged_in? 
    cookies.delete :auth_token 
    reset_session 
    flash[:notice] = "You have been logged out." 
    redirect_back_or_default('/') 
end 

En el controlador de aplicación que tiene:

before_filter :login_required 

y en el sessions_controller que tengo:

skip_before_filter :login_required 

Mi problema es que cuando un usuario se autentica con la autenticación HTTP básica, no se desconecta. la sesión se destruye, pero el usuario puede navegar a páginas restringidas sin ningún problema. Este problema no ocurre con la autenticación de sesión a través del complemento. ¿Cómo puedo hacer que este método elimine la autentificación básica?

+0

Las sesiones no son REST. – deamon

Respuesta

13

Nada se puede hacer de servidor para "cerrar sesión" a un usuario en esta situación. Cuando el usuario inicia sesión a través de la autenticación básica, el navegador almacena la información de autenticación y envía los parámetros de autenticación a través de los encabezados http con cada solicitud. si el usuario inicia sesión con autenticación básica, deberá cerrar la ventana de su navegador para cerrar la sesión.

+1

Esto es un poco un truco, pero resolvió mi problema. Redirija al usuario a una URL con una identificación de usuario incorrecta incrustada en ella. http://stackoverflow.com/questions/5957822/how-to-clear-basic-authentication-details-in-chrome – Snekse

+0

La sugerencia de Snekse de la otra pregunta SO también funcionó para mí. –

1

Hmm, parece que el navegador del cliente simplemente está almacenando en caché las credenciales de autenticación básica de HTTP y las vuelve a enviar cada vez. En ese caso, no tienes control sobre eso. Las acciones que se desea proteger necesidad de ser protegida con el before_filter adecuada para el plugin restful_authentication, que debe ser

require_authentication 

Así que en su controlador que tendría

before_filter :require_authentication 

autenticación HTTP no tiene estado - es decir, el servidor no realiza un seguimiento de una "sesión" autenticada, por lo tanto, el cliente debe proporcionarla cada vez (de ahí la casilla de verificación frecuente 'almacenar estas credenciales'), por lo tanto, no hay forma de que el servidor borre las credenciales del cliente . Esto es parte de la especificación. Ver la entrada de Wikipedia

http://en.wikipedia.org/wiki/Basic_access_authentication

Específicamente, mira la sección "desventajas".

+0

edité el código para mostrar los filtros anteriores que tengo –

1

acabo login_from_basic_auth actualizada en authenticated_sytem a leer:

def login_from_basic_auth 
     false 
#  authenticate_with_http_basic do |login, password| 
#  self.current_user = User.authenticate(login, password) 
#  end 
    end 
+1

el problema con esta solución es que simplemente desactiva la autenticación HTTP básica, que no es lo que quiero hacer. Además, si desea desactivar la autenticación básica de esta manera, debe eliminar la llamada a este método dentro de def current_user en lugar de reescribirla. –

4

He encontrado una manera bastante interesante de superar esto mediante el uso de una variable de sesión para recordar qué usuario ha cerrado sesión. La idea es que, aunque el navegador todavía envía datos de autenticación, simplemente lo ignoramos, porque el usuario decidió cerrar la sesión. Cada vez que se envía una nueva solicitud de inicio de sesión al navegador, todos los datos de autenticación se borran, por lo que el usuario puede volver a iniciar sesión en cualquier momento.

class ApplicationController < ActionController::Base 
    # ... 

    before_filter :authenticate 

    protected 

    def authenticate 
    authenticate_with_http_basic do |username, password| 
     @current_user = User.find_by_name_and_crypted_password(username, User.digest(password)) 
     @current_user = nil if @current_user && session[:logged_out] == @current_user.id 
     [email protected]_user.nil? 
    end 
    end 

    def authenticate! 
    return if @current_user 
    session[:authenticate_uri] = request.request_uri 
    redirect_to('/login') 
    end 
end 

Luego, en el controlador de eventos que hago:

class EventsController < ApplicationController 
    before_filter :authenticate!, :only => [ :new, :create, :edit, :update ] 
    #... 
end 

Y por último, mi controlador de la sesión tiene el siguiente aspecto:

class SessionController < ApplicationController 
    before_filter :authenticate!, :only => [ :create ] 

    def create 
    if session[:authenticate_uri] 
     redirect_to(session[:authenticate_uri]) 
     session[:authenticate_uri] = nil 
    else 
     redirect_to(new_event_path) 
    end 
    end 

    def destroy 
    session[:logged_out] = @current_user.id 
    redirect_to '/' 
    end 

    protected 

    def authenticate! 
    authenticate_or_request_with_http_basic("Rankings") do |username, password| 
     @current_user = User.find_by_name_and_crypted_password(username, User.digest(password)) 
     if @current_user && session[:logged_out] == @current_user.id 
     @current_user = nil 
     session[:logged_out] = nil 
     end 
     [email protected]_user.nil? 
    end 
    end 

end 

y no se olvide de sus rutas!

map.logout 'login', :controller => 'session', :action => 'create' 
    map.logout 'logout', :controller => 'session', :action => 'destroy' 
+0

gracias. eres increíble – khanh

2

Esto sólo funciona para IE 6 SP1 +:

javascript:void(document.execCommand('ClearAuthenticationCache', false)); 

http://msdn.microsoft.com/en-us/library/ms536979(VS.85).aspx

Tenga en cuenta que esto borrará la caché de todos los sitios que el usuario está conectado actualmente (dentro de la misma instancia de IE) .

1

Una forma de solucionar este problema es desactivar "autenticación HTTP básica" completamente

Pero necesitaba esto para una buena experiencia del usuario durante las acciones de Ajax, lo que permitió a esta autenticación sólo para acciones ajax

def login_from_basic_auth 

    return false unless request.xhr? 

    authenticate_with_http_basic do |login, password| 
    self.current_user = User.authenticate(login, password) 
    end 
end 
1

sé que, poco después de la fiesta, pero si desea desconectarse puedo rendir 401.

método de cierre de sesión por lo pude tiene este aspecto:

def logout 
    render :logout, status: 401 
end 

su acción relajante pude tiene este aspecto:

def destroy 
    self.current_user.forget_me if logged_in? 
    cookies.delete :auth_token 
    reset_session 
    redirect_to '/', status: 401, flash: "You have been logged out." 
end 

y el navegador va a aumentar de nuevo la autenticación básica HTTP

Cuestiones relacionadas