无需创建 Devise 用户即可验证自定义策略

发布于 2024-11-19 11:22:21 字数 969 浏览 2 评论 0原文

我的设置:Rails 3.0.9、Ruby 1.9.2、Devise 1.3.4、Warden 1.0.4

我试图弄清楚是否可以验证自定义策略,而不必在成功后在此过程中创建设计用户验证。在我的 config.warden 块中,身份验证工作正常,但如果我不创建 Devise 用户,我将不会通过身份验证。我的理想场景要求我成功地针对第 3 方提供商进行身份验证并登录到我的应用程序(使用没有相应 Devise 用户记录的 Devise),或者如果我无法进行身份验证,则尝试 Devise 标准登录路径。

这是我正在工作的 devise.rb 代码片段,但我必须创建一个 devise 用户才能进行身份验证,这是我希望避免的事情

config.warden do |manager|
    manager.strategies.add(:custom_strategy) do
      def valid?
        params[:user] && params[:user][:email] && params[:user][:password]
      end

      def authenticate!
        ...perform authentication against 3rd party provider...
        if successful_authentication
          u = User.find_or_initialize_by_email(params[:user][:email])
          if u.new_record?
            u.app = 'blah'
            u.save
          end
          success!(u)
        end
      end
    end

manager.default_strategies(:scope => :user).unshift :custom_strategy
  end

My setup: Rails 3.0.9, Ruby 1.9.2, Devise 1.3.4, Warden 1.0.4

I'm trying to figure out if it possible to authenticate a custom strategy and not have to create a devise user in the process upon successful authentication. In my config.warden block, the authentication works fine but if I don't create a Devise user, I won't be authenticated. My ideal scenario requires me to either successfully authenticate against a 3rd party provider and sign into my app (using Devise without a corresponding Devise user record) or if I fail to authenticate, then try Devise standard login path.

Here is the devise.rb code snippet I got working but I have to create a devise user for the authentication to work, this is something I wish to avoid

config.warden do |manager|
    manager.strategies.add(:custom_strategy) do
      def valid?
        params[:user] && params[:user][:email] && params[:user][:password]
      end

      def authenticate!
        ...perform authentication against 3rd party provider...
        if successful_authentication
          u = User.find_or_initialize_by_email(params[:user][:email])
          if u.new_record?
            u.app = 'blah'
            u.save
          end
          success!(u)
        end
      end
    end

manager.default_strategies(:scope => :user).unshift :custom_strategy
  end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

栩栩如生 2024-11-26 11:22:21

我意识到这个问题很老了,但当我寻找类似问题的解决方案时,我看到了几次,所以我决定发布答案,以防将来有人偶然发现类似问题。希望这会有所帮助!

我最近不得不做类似的事情->我的数据库中的用户通过某些设计/管理员策略进行了身份验证,但创建了另一个应用程序,该应用程序必须有权访问我的应用程序的某些端点。基本上我想做 HMAC 身份验证。
但我不想在该过程中涉及任何用户对象,这就是我必须做的(假设您已经有了在不使用用户对象的情况下验证传入请求的自定义策略)

  1. 创建一个使用的假用户模型,以便设计不会失败。您不必为

我的表创建任何数据库表,如下所示:

class Worker # no need to create  a table for him
  extend ActiveModel::Callbacks
  extend Devise::Models

  include ActiveModel::Validations
  include Concerns::ObjectlessAuthenticatable

  define_model_callbacks :validation

  attr_accessor :id

  def persisted
    false
  end

  def initialize(id)
    @id = id
  end

  def self.serialize_from_session(id)
    self.new(id: id)
  end

  def self.serialize_into_session(record)
    [record.id]
  end

  def self.http_authenticatable
    false
  end
end

然后在设计初始值设定项 (/initializers/devise.rb) 中,我添加了单独的身份验证策略,如下所示:

  ...
  config.warden do |manager|
    manager.scope_defaults :user, :strategies => [
      ...strategies i was using for users
    ]
    manager.scope_defaults :worker, :strategies => [:worker_authentication], store: false, action: 'unautenticated_worker'
    manager.failure_app = CustomFailingApp
  end
  ...

然后在 中routes.rb 我必须创建一个映射供设计使用,这样

devise_for :worker # you can pass some custom options here

无论我需要验证工作人员,而不是我只需调用(在控制器中)的用户authenticate_worker!

I realized the question is old but I saw it a couple of time when I was searching for a solution to similar thing so I decided to post the answer in case anyone in the future stumbles upon similar issue. Hope this will help!

I recently had to do similar thing -> had users in my database that were authenticated with some devise/warden strategies but had created another app that has to have access to some of the endpoints to my application. Basically I wanted to do a HMAC authentication.
But I didn't want to involve any user objects in that process and here is what I had to do (provided that you already have you custom strategy that authenticates incoming request without using user object)

  1. create a fake user model that is used so that devise wont blow op. You dont have to create any database table for that

mine looked similar to below:

class Worker # no need to create  a table for him
  extend ActiveModel::Callbacks
  extend Devise::Models

  include ActiveModel::Validations
  include Concerns::ObjectlessAuthenticatable

  define_model_callbacks :validation

  attr_accessor :id

  def persisted
    false
  end

  def initialize(id)
    @id = id
  end

  def self.serialize_from_session(id)
    self.new(id: id)
  end

  def self.serialize_into_session(record)
    [record.id]
  end

  def self.http_authenticatable
    false
  end
end

then in devise initializer (/initializers/devise.rb) I've added separate authentication strategy like below:

  ...
  config.warden do |manager|
    manager.scope_defaults :user, :strategies => [
      ...strategies i was using for users
    ]
    manager.scope_defaults :worker, :strategies => [:worker_authentication], store: false, action: 'unautenticated_worker'
    manager.failure_app = CustomFailingApp
  end
  ...

then in routes.rb I had to create a mapping for devise to use like so

devise_for :worker # you can pass some custom options here

then wherever I needed to authenticate the worker, not the user I just had to call (in the controller) authenticate_worker!

忆悲凉 2024-11-26 11:22:21

我希望这违背了设计的设计,其中所有操作都是使用资源的静态路由来完成的。也就是说,Warden 的 success! 方法中的注释是这样说的:

# Parameters:
#   user - The user object to login.  This object can be anything you have setup to serialize in and out of the session

那么你能不能将对象 u 更改为代表用户的其他对象,比如普通的旧哈希吗?

I would expect that this is against the design of devise where all actions are done using restful routes for a resource. That said, the comments in Warden's success! method say:

# Parameters:
#   user - The user object to login.  This object can be anything you have setup to serialize in and out of the session

So could you not change the object u to some other object that represents the user, like a plain old Hash?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文