Переключение Разрабатывать модули аутентификации для каждого действия контроллера - PullRequest
3 голосов
/ 04 ноября 2010

У меня есть сайт Rails, который использует Devise для аутентификации. У меня есть одна страница (PhotosController#create), которая должна аутентифицировать пользователей без файлов cookie. Я делаю это с помощью модуля :token_authenticatable Devise, который аутентифицирует пользователя, если предоставленный токен совпадает с токеном, хранящимся на стороне сервера. (См. этот ТАК вопрос , если вам интересно.)

Хорошей политикой является истечение срока действия или смена токена после завершения действия. Это не позволяет злоумышленнику прослушать токен и использовать его для успешной аутентификации пользователя. Однако в моем случае я не могу истечь или изменить маркер, потому что загрузчик фотографий на стороне клиента загружает несколько фотографий, каждая из которых приводит к отдельной POST до PhotosController#create. Поэтому, если я удаляю токен после успешного создания, вторая, третья и т. Д. Загрузка завершится неудачей.

Разработать модули указываются на уровне модели (например, модель User). Мне нужно больше детализации, чем эта.

У меня вопрос, как включить модуль :token_authenticatable только для одного действия одного контроллера? Или, эквивалентно, как отключить модуль :token_authenticatable для всех контроллеров и действий , кроме для одного действия?

Ответы [ 4 ]

7 голосов
/ 04 ноября 2010

Как разработчик одного плагина devise (devise_rpx_connectable) я с удовольствием отвечу на ваш вопрос.

TokenAuthenticatable - это одна из стратегий Devise, вы можете прочитать ее код здесь:

https://github.com/plataformatec/devise/blob/master/lib/devise/strategies/token_authenticatable.rb

Как видите, каждая стратегия разработки имеет действительный?и / или valid_request?метод, который вызывается, чтобы определить, должна ли стратегия быть включена.Таким образом, вы можете легко переопределить эту стратегию для своих нужд, или вы можете также переопределить только valid_request?метод.Просто загрузите этот тип кода в инициализатор (ПОСЛЕ устройства, разумеется, загруженного):

module Devise
  module Strategies
    class TokenAuthenticatable < Authenticatable
      private
      def valid_request?
        params[:controller] == "photos" && params[:action] == "create"
      end
    end
  end
end

Я не проверял это, я не знаю, работает ли он из коробки, но я надеюсь, что выпосмотрите, если это не сработает, используйте отладчик или напишите собственную стратегию разработки (см. мой плагин, это легко понять) и т. д.

Более того, когда вы используете эту стратегию, пользовательбудет храниться в сеансе, если вы не используете опцию stateless_token, см .: https://github.com/plataformatec/devise/blob/master/lib/devise/models/token_authenticatable.rb#L27

2 голосов
/ 20 сентября 2011

Поместите это в инициализатор

require 'devise/strategies/base'
require 'devise/strategies/token_authenticatable'
module Devise
  module Strategies
    class TokenAuthenticatable < Authenticatable
      private
      def valid_request?
        params[:controller] == "photos" && params[:action] == "create"
      end
    end
  end
end
1 голос
/ 10 августа 2012

Самое простое решение можно найти здесь: Разработать возможность аутентификации токена на одном действии контроллера Мои извинения, но я не знаю, как пометить вопрос как возможное повторение и т. Д. Упомянутое решениеработал для меня, используя рельсы 3.2.7.

Таким образом, он не использует def valid_request?, который является закрытым и не может быть вызван напрямую из класса извне.(проверьте базовый код для стратегии на https://github.com/plataformatec/devise/blob/master/lib/devise/strategies/authenticatable.rb#L15). Поэтому не совсем лучшее место для переопределения.Вместо этого вы должны использовать valid? и иметь что-то вроде этого:

require 'devise/strategies/base'
require 'devise/strategies/token_authenticatable'
module Devise
  module Strategies
    class TokenAuthenticatable < Authenticatable
      def valid?
        super && params[:controller] == "your controller" && params[:action] == "your action"
      end
    end
  end
end
1 голос
/ 12 ноября 2010
Подход

slainer68 хорош, но он не работает для меня как есть, поэтому я добавлю свое возможное решение здесь.

В config/initializers/devise.rb, в котором уже был блок Devise.setup do |config| ... end,Я добавил следующее:

Warden::Strategies.add(:my_token_authenticatable, Devise::Strategies::TokenAuth
  def valid?
    mapping.to.respond_to?(:authenticate_with_token) && authentication_token(scope).present? && params[:controller] == 'photos' && params[:action] == 'create'
  end
end

Я также добавил это в блок Devise.setup:

config.warden do |manager|
  manager.default_strategies.unshift :my_token_authenticatable
end

Было бы лучше просто обновить существующую стратегию :token_authenticatable, ноэто не было загружено в Warden к тому времени, когда этот код был выполнен.В результате использования стратегии с другим именем мне пришлось продублировать некоторые методы и методы класса из Devise::Strategies::TokenAuthenticatable, в том числе:

  • reset_authentication_token
  • reset_authentication_token!
  • self.authenticate_with_token(attributes)
  • self.token_authentication_key
  • valid_authentication_token?(incoming_auth_token)
  • self.find_for_token_authentication(token)

Мне также пришлосьremove: token_authenticatable из строки devise в верхней части модели User.

Я также воспользовался советом slainer68 и добавил :stateless_token => false в опции для devise_for в config/routes.rb.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...