Выйдите из системы с помощью http-базовой аутентификации и плагина restful_authentication - PullRequest
9 голосов
/ 19 марта 2009

У меня установлен плагин restful_authentication, установленный в приложении rails, с session_controller, у которого есть метод уничтожения, подобный этому:

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

В контроллере приложения у меня есть:

before_filter :login_required

А в сессионном контроллере у меня есть:

skip_before_filter :login_required

Моя проблема в том, что, когда пользователь проходит аутентификацию с помощью базовой HTTP-аутентификации, он / она не выходит из системы. сеанс уничтожен, но пользователь может без проблем переходить на закрытые страницы. Эта проблема не возникает при аутентификации сеанса через плагин. Как я могу заставить этот метод избавиться от базовой аутентификации?

Ответы [ 7 ]

13 голосов
/ 13 апреля 2009

Ничего нельзя сделать на стороне сервера, чтобы «выйти» из этой ситуации. Когда пользователь входит в систему с помощью обычной аутентификации, браузер сохраняет информацию аутентификации и отправляет параметры аутентификации через заголовки http при каждом запросе. если пользователь входит в систему с базовой аутентификацией, ему / ей придется закрыть окно своего браузера для выхода из системы.

4 голосов
/ 09 июля 2009

Я нашел довольно интересный способ преодолеть это, используя переменную сеанса, чтобы запомнить, какой пользователь вышел из системы. Идея состоит в том, что, хотя браузер все еще отправляет данные аутентификации, мы просто игнорируем их, потому что пользователь решил выйти из системы. Всякий раз, когда в браузер отправляется новый запрос на вход, все данные аутентификации стираются, поэтому пользователь может в любой момент вернуться в систему.

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'
2 голосов
/ 07 августа 2010

Это работает только для IE 6 SP1 +:

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

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

Обратите внимание, что это очистит кэш для всех сайтов, на которых пользователь в данный момент вошел (в том же экземпляре IE).

1 голос
/ 25 июня 2015

Я знаю, немного после вечеринки, но если вы хотите выйти из системы, вы можете сделать 401.

поэтому метод выхода из системы может выглядеть следующим образом:

def logout
  render :logout, status: 401
end

Ваше спокойное действие может выглядеть так:

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

и браузер снова вызовет базовую аутентификацию http

1 голос
/ 31 августа 2010

Один из способов исправить это - полностью отключить «базовую аутентификацию http»

Но нам нужно было это для хорошего пользовательского опыта во время действий Ajax, поэтому мы включили эту аутентификацию только для действий 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 голос
/ 10 апреля 2009

Я только что обновил login_from_basic_auth в authenticated_sytem, ​​чтобы прочитать:

    def login_from_basic_auth
      false
#      authenticate_with_http_basic do |login, password|
#        self.current_user = User.authenticate(login, password)
#      end
    end
1 голос
/ 19 марта 2009

Хм, похоже, что клиентский браузер просто кэширует учетные данные HTTP Basic Auth и повторно отправляет их каждый раз. В этом случае вы не можете это контролировать. Действия, которые вы хотите защитить, должны быть защищены соответствующим before_filter для плагина restful_authentication, который должен быть

require_authentication

Так что в вашем контроллере вы бы

before_filter :require_authentication

HTTP-аутентификация не имеет состояния, то есть сервер не отслеживает аутентифицированный «сеанс» - таким образом, клиент должен предоставлять его каждый раз (отсюда и частый флажок «хранить эти учетные данные»), таким образом, нет никакого способа для сервера, чтобы очистить учетные данные клиента. Это часть спецификации. Смотрите запись в Википедии

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

В частности, посмотрите раздел «Недостатки».

...