每个控制器操作切换Devise身份validation模块

我有一个使用Devise进行身份validation的Rails站点。 我有一个页面( PhotosController#create )需要在没有cookie的情况下对用户进行身份validation。 我正在使用Devise的:token_authenticatable模块执行此操作,如果提供的令牌与存储在服务器端的令牌匹配,则会对用户进行身份validation。 (如果你很好奇,请参阅这个问题 。)

在操作完成后过期或更改令牌是一个很好的策略。 这可以防止攻击者嗅探令牌并使用它成功地作为用户进行身份validation。 但是,在我的情况下,我无法过期或更改令牌,因为客户端照片上传器上传了多张照片,每张照片都会导致一个单独的POST到PhotosController#create 。 因此,如果我在成功创建后使令牌到期,则第二次,第三次等上传将失败。

设计模块在模型级别指定(例如User模型)。 我需要更多的粒度。

我的问题是,如何针对单个控制器的单个操作启用:token_authenticatable模块? 或者,等效地,如何为一个操作之外的所有控制器和操作禁用:token_authenticatable模块?

作为一个设计插件的开发者(devise_rpx_connectable),我很乐意回答你的问题。

TokenAuthenticatable是一个Devise策略,你可以在这里阅读它的代码:

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

如您所见,每个设计策略都有效吗? 和/或valid_request? 调用的方法,用于确定是否应启用策略。 因此,您可以根据需要轻松覆盖此策略,或者您也可以仅覆盖valid_request? 方法。 只需在初始化程序中加载此类代码(当然加载AFTER设计):

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

我没有测试过这个,我不知道是否可以开箱即用,但我希望你能看到重点,如果不起作用,请使用调试器,或编写自己的Devise策略(参见我的插件,它是容易理解)等

此外,当您使用此策略时,除非您使用stateless_token选项,否则用户将存储在会话中,请参阅: https : //github.com/plataformatec/devise/blob/master/lib/devise/models/token_authenticatable.rb# L27

把它放在初始化器中

 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 

slainer68的方法很好,但它对我不起作用,所以我将在这里添加我的最终解决方案。

config/initializers/devise.rb ,已经有一个Devise.setup do |config| ... end 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)

我还必须从User模型顶部的devise行中删除:token_authenticatable。

我还采用了slainer68的建议,并在config/routes.rb添加了:stateless_token => falsedevise_for的选项。

最简单的解决方案可以在这里找到: 设计允许在单个控制器操作上进行令牌认证我很抱歉,但我不知道如何将问题标记为可能的重复,等等。所提到的解决方案对我使用rails 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