Pergunta

Eu tenho o restful_authentication plugin instalado em um app Rails, com um sessions_controller que tem um método destruir assim:

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

No controlador aplicativo eu tenho:

before_filter :login_required

E no sessions_controller eu tenho:

skip_before_filter :login_required

O meu problema é que quando um usuário se autentica com http autenticação básica, ele / ela não está desconectado. a sessão é destruída, mas o usuário é capaz de navegar para páginas restritas sem nenhum problema. Este problema não ocorre com autenticação de sessão através do plugin. Como posso fazer este método se livrar do authenication básica?

Foi útil?

Solução

Nada pode ser feito do lado do servidor para "logout" um usuário nesta situação. Quando o usuário faz login através de autenticação básica, o navegador armazena as informações de autenticação e envia os parâmetros de autenticação através do http cabeçalhos com cada pedido. Se o usuário fizer login com autenticação básica, ele / ela terá que fechar a janela his / her navegador para sair.

Outras dicas

Eu encontrei uma maneira bastante interessante para superar isso usando uma variável de sessão para lembrar que o usuário se desconectou. A idéia é que mesmo que o navegador ainda está enviando dados de autenticação, estamos apenas ignorá-lo, porque o usuário escolheu para encerrar a sessão. Sempre que uma nova solicitação de login é enviado para o navegador, todos os dados de autenticação é apagado, de modo que o usuário é capaz de fazer login novamente em qualquer altura.

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

Em seguida, sobre os acontecimentos controlador de I fazer:

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

E, finalmente, a minha sessão controlador esta aparência:

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

E não esqueça suas rotas!

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

Isso só funciona para o IE 6 SP1 +:

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

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

Note que isso irá limpar o cache para todos os sites que o usuário está conectado em (dentro da mesma instância IE).

Hmm, parece que o navegador do cliente é apenas o cache as credenciais de autenticação do HTTP Básico e re-enviá-los o tempo todo. Caso em que você não tem controle sobre isso. As ações que você deseja ser protegido necessidade de ser protegida com o before_filter adequada para o plugin restful_authentication, que deve ser

require_authentication

Assim, em seu controlador você teria

before_filter :require_authentication

HTTP Authentication é apátrida - isto é, o servidor não manter o controle de uma "sessão" autenticado - assim, o cliente deve fornecê-lo cada vez que (daí a opção freqüente 'armazenar essas credenciais'), assim não há nenhuma maneira para o servidor para limpar as credenciais do cliente. Esta é parte da especificação. Veja a entrada Wikipedia

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

Especificamente, olhe para a seção "Desvantagens".

Eu login_from_basic_auth em authenticated_sytem acaba de atualizar para ler:

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

Uma maneira de corrigir isso é desativar "básica http autenticação" completamente

Mas precisávamos isso por boa experiência do usuário durante as ações Ajax, por isso habilitado essa autenticação apenas para ações 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

Eu sei, pouco depois da festa, mas se você quer sair você pode processar 401.

Assim o método de logout poderiam esta aparência:

def logout
  render :logout, status: 401
end

sua ação repousante poderia esta aparência:

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

eo navegador irá aumentar http básica de autenticação novamente

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top