2011-12-01 148 views
1

我在我的應用程序中有restful_authentication。有了這個會議控制器。除了一件事以外,一切都爲我工作。當窗口關閉並在同一臺機器上重新打開時,應用程序狀態將被保存,包括已登錄的用戶。我需要我的應用程序在瀏覽器窗口關閉時將用戶註銷。但我不知道如何讓它發生。是否有東西導致它保存,還是我需要添加一些東西來殺死它?關閉窗口時註銷

這裏是會話控制器:

# This controller handles the login/logout function of the site. 
class SessionsController < ApplicationController 

    # render new.rhtml 
    def new 
    end 

    def create 
    logout_keeping_session! 
    user = User.authenticate(params[:login], params[:password]) 
    if user 
     unless user.active? 
     # ensures "deleted" users can't login 
     user = nil 
     end 
    end 
    if user 
     # Protects against session fixation attacks, causes request forgery 
     # protection if user resubmits an earlier form using back 
     # button. Uncomment if you understand the tradeoffs. 
     # reset_session 
     self.current_user = user 
     new_cookie_flag = (params[:remember_me] == "1") 
     handle_remember_cookie! new_cookie_flag 
     redirect_back_or_default('/') 
    else 
     note_failed_signin 
     @login  = params[:login] 
     @remember_me = params[:remember_me] 
     render :action => 'new' 
    end 
    end 

    def destroy 
    logout_killing_session! 
    redirect_back_or_default('/', :notice => "You have been logged out.") 
    end 

protected 
    # Track failed login attempts 
    def note_failed_signin 
    flash.now[:alert] = "Couldn't log you in as '#{params[:login]}'" 
    logger.warn "Failed login for '#{params[:login]}' from #{request.remote_ip} at #{Time.now.utc}" 
    end 
end 

這裏是authenticatedSystem模塊(顯然不相關的材料移除)

module AuthenticatedSystem 
    protected 
    # Returns true or false if the user is logged in. 
    # Preloads @current_user with the user model if they're logged in. 
    def logged_in? 
     !!current_user 
    end 

    # Accesses the current user from the session. 
    # Future calls avoid the database because nil is not equal to false. 
    def current_user 
     @current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie) unless @current_user == false 
    end 

    # Store the given user id in the session. 
    def current_user=(new_user) 
     session[:user_id] = new_user ? new_user.id : nil 
     @current_user = new_user || false 
    end 


    def authorized?(action = action_name, resource = nil) 
     logged_in? 
    end 


    def login_required 
     authorized? || access_denied 
    end 


    def access_denied 
     respond_to do |format| 
     format.html do 
      store_location 
      redirect_to new_session_path 
     end 
     # format.any doesn't work in rails version < http://dev.rubyonrails.org/changeset/8987 
     # Add any other API formats here. (Some browsers, notably IE6, send Accept: */* and trigger 
     # the 'format.any' block incorrectly. See http://bit.ly/ie6_borken or http://bit.ly/ie6_borken2 
     # for a workaround.) 
     format.any(:json, :xml) do 
      request_http_basic_authentication 'Web Password' 
     end 
     end 
    end 

    # Store the URI of the current request in the session. 
    # 
    # We can return to this location by calling #redirect_back_or_default. 
    def store_location 
     session[:return_to] = request.fullpath 
    end 

    # Redirect to the URI stored by the most recent store_location call or 
    # to the passed default. Set an appropriately modified 
    # after_filter :store_location, :only => [:index, :new, :show, :edit] 
    # for any controller you want to be bounce-backable. 
    def redirect_back_or_default(default, options = {}) 
     redirect_to((session[:return_to] || default), options) 
     session[:return_to] = nil 
    end 

    # Inclusion hook to make #current_user and #logged_in? 
    # available as ActionView helper methods. 
    def self.included(base) 
     base.send :helper_method, :current_user, :logged_in?, :authorized? if base.respond_to? :helper_method 
    end 

    # 
    # Login 
    # 

    # Called from #current_user. First attempt to login by the user id stored in the session. 
    def login_from_session 
     self.current_user = User.find_by_id(session[:user_id]) if session[:user_id] 
    end 

    # Called from #current_user. Now, attempt to login by basic authentication information. 
    def login_from_basic_auth 
     authenticate_with_http_basic do |login, password| 
     self.current_user = User.authenticate(login, password) 
     end 
    end 

    # 
    # Logout 
    # 

    # Called from #current_user. Finaly, attempt to login by an expiring token in the cookie. 
    # for the paranoid: we _should_ be storing user_token = hash(cookie_token, request IP) 
    def login_from_cookie 
     user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token]) 
     if user && user.remember_token? 
     self.current_user = user 
     handle_remember_cookie! false # freshen cookie token (keeping date) 
     self.current_user 
     end 
    end 

    # This is ususally what you want; resetting the session willy-nilly wreaks 
    # havoc with forgery protection, and is only strictly necessary on login. 
    # However, **all session state variables should be unset here**. 
    def logout_keeping_session! 
     # Kill server-side auth cookie 
     @current_user.forget_me if @current_user.is_a? User 
#  @current_user = false  # not logged in, and don't do it for me 
     kill_remember_cookie!  # Kill client-side auth cookie 
     session[:user_id] = nil # keeps the session but kill our variable 
     # explicitly kill any other session variables you set 
    end 

    # The session should only be reset at the tail end of a form POST -- 
    # otherwise the request forgery protection fails. It's only really necessary 
    # when you cross quarantine (logged-out to logged-in). 
    def logout_killing_session! 
     logout_keeping_session! 
     reset_session 
    end 

回答

1

當用戶重新打開瀏覽器,你是從驗證他們曲奇餅。嘗試從

def current_user 
    @current_user ||= (login_from_session || login_from_basic_auth) unless @current_user == false 
end 
+0

'def login_from_cookie user = cookies [:auth_token] && User.find_by_remember_token(cookies [:auth_token]) if user && user.remember_token? self.current_user = user handle_remember_cookie!假#清新的cookie令牌(保留日期) self.current_user end end'
只有在選擇「remember_me」選項時纔會起作用,我已禁用它。 –

+0

如果這是真的,那麼你需要認真研究認證系統。在您打開新瀏覽器時登錄的唯一可能方式是Cookie。 –

+0

事實證明,這是工作正常的IE8,不幸的是我的目標瀏覽器。所以我想現在真的是一個緊迫的問題。 (想象一下,在IE上正常工作!) –

3

發生這種情況時,您的瀏覽器(Firefox中,在我的情況)啓動偏好設置爲「顯示我的窗口和標籤,從最後一次」清除login_from_cookie。當您在關閉瀏覽器(所有窗口)時「在下次啓動時保存您的選項卡」時也會發生這種情況。在這些情況下,瀏覽器會記住會話,即它不像通常那樣刪除會話cookie。

+0

是的......可能是這種情況。我需要一種方法來強制它關閉該cookie。 –

+0

你在做什麼。在Windows中,它在IE8,opera和safari中是正確的,但不是chrome。在OSX上,它保存所有瀏覽器上的登錄信息。 –