我找到了一种非常有趣的方法来克服这个问题,方法是使用会话变量来记住哪个用户已注销。这个想法是即使浏览器仍在发送身份验证数据,我们只是忽略它,因为用户选择注销。每当向浏览器发送新的登录请求时,所有身份验证数据都会被删除,因此用户可以随时重新登录。
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
!@current_user.nil?
end
end
def authenticate!
return if @current_user
session[:authenticate_uri] = request.request_uri
redirect_to('/login')
end
end
然后,在事件控制器上我做:
class EventsController < ApplicationController
before_filter :authenticate!, :only => [ :new, :create, :edit, :update ]
#...
end
最后我的会话控制器看起来像这样:
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
!@current_user.nil?
end
end
end
并且不要忘记您的路线!
map.logout 'login', :controller => 'session', :action => 'create'
map.logout 'logout', :controller => 'session', :action => 'destroy'