2009-03-18 7 views
9

ich die restful_authentication Plugin in einer Schienen app installiert ist, mit einem sessions_controller, die eine Zerstörung Methode wie folgt hat:Logout mit HTTP-Basisauthentifizierungs und restful_authentication Plugin

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 

In dem Anwendungscontroller ich habe:

before_filter :login_required 

und in der sessions_controller ich habe:

skip_before_filter :login_required 

Mein Problem ist, dass wenn ein Benutzer sich mit der http-Standardauthentifizierung authentifiziert, er/sie nicht ausgeloggt wird. Die Sitzung ist zerstört, aber der Benutzer kann problemlos zu eingeschränkten Seiten navigieren. Dieses Problem tritt bei der Sitzungsauthentifizierung über das Plugin nicht auf. Wie kann ich mit dieser Methode die grundlegende Authentifizierung entfernen?

+0

Sessions sind nicht RESTful. – deamon

Antwort

13

Nichts serverseitige getan werden kann, um "Logout" einen Benutzer in dieser Situation. Wenn sich der Benutzer über die Standardauthentifizierung anmeldet, speichert der Browser die Authentifizierungsinformationen und sendet die Authentifizierungsparameter über die HTTP-Header bei jeder Anforderung. Wenn sich der Benutzer mit basic auth anmeldet, muss er/sie sein/ihr Browserfenster schließen, um sich abzumelden.

+1

Dies ist ein bisschen wie ein Hack, aber es hat mein Problem gelöst. Leiten Sie den Benutzer zu einer URL um, in die eine ungültige Benutzer-ID eingebettet ist. http://stackoverflow.com/questions/5957822/how-to-clear-basic-authentication-details-in-chrome – Snekse

+0

Snekse Vorschlag von der anderen Frage SO für mich gearbeitet als auch. –

1

Hmm, es klingt wie der Client-Browser nur die HTTP Basic Auth-Anmeldeinformationen zwischenspeichert und jedes Mal erneut sendet. In diesem Fall haben Sie keine Kontrolle darüber. Die Aktionen, die Sie wollen, müssen geschützt werden, um mit der richtigen before_filter für das restful_authentication Plugin geschützt werden, die in dem Controller sollte

require_authentication 

So würden Sie

before_filter :require_authentication 

HTTP-Authentifizierung haben staatenlos ist - Das heißt, der Server verfolgt keine authentifizierte "Sitzung" - der Client muss sie daher jedes Mal bereitstellen (daher das häufige Kontrollkästchen "diese Anmeldeinformationen speichern"), so dass der Server die Client-Anmeldeinformationen nicht löschen kann . Dies ist Teil der Spezifikation. Siehe Wikipedia-Eintrag

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

Insbesondere, Blick auf die "Nachteile" Abschnitt.

+0

bearbeitet den Code, um die vor Filter zu zeigen, ich habe –

1

I aktualisiert login_from_basic_auth nur in authenticated_sytem zu lesen:

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

das Problem mit dieser Lösung ist, dass es einfach http-Basisauthentifizierung deaktiviert, was ist nicht was ich tun möchte. Wenn Sie die Basisauthentifizierung auf diese Weise deaktivieren möchten, sollten Sie den Aufruf dieser Methode in def current_user entfernen und nicht neu schreiben. –

4

Ich habe einen recht interessanten Weg gefunden, dies zu überwinden, indem ich eine Sitzungsvariable benutze, um mich daran zu erinnern, welcher Benutzer ausgeloggt ist. Die Idee ist, dass, obwohl der Browser immer noch Authentifizierungsdaten sendet, wir es einfach ignorieren, weil der Benutzer sich abgemeldet hat. Wenn eine neue Anmeldeanforderung an den Browser gesendet wird, werden alle Authentifizierungsdaten gelöscht, sodass sich der Benutzer jederzeit wieder anmelden kann.

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 

Dann wird auf der Ereignisse Controller ich tun:

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

Und schließlich sieht meine Session-Controller wie folgt aus:

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 

Und vergessen Sie nicht, Ihre Routen!

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

danke. du bist unglaublich – khanh

2

Dies funktioniert nur für IE 6 SP1 +:

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

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

Beachten Sie, dass dies den Cache für alle Websites löschen wird der Benutzer zur Zeit in (innerhalb der gleichen IE-Instanz) angemeldet ist .

1

Eine Möglichkeit, dies zu beheben, ist „grundlegende HTTP-Authentifizierung“ vollständig

Aber wir mussten dies für eine gute User Experience während Ajax Aktionen zu deaktivieren, so aktiviert wir diese Authentifizierung nur für Ajax-Aktionen

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

ich weiß, wenig nach der Party, aber wenn Sie sich ausloggen möchten, können Sie 401.

so Logout-Methode machen könnte wie folgt aussieht:

def logout 
    render :logout, status: 401 
end 

Ihre ruhige Aktion könnte wie folgt aussieht:

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 

und Browser http Standardauthentifizierung erhöhen wieder

Verwandte Themen