1

我正在尝试关注博客文章以允许使用设计进行远程身份验证,但我无法弄清楚一些事情。

我怎么称呼我的新文件,我把它们放在哪里?

第一个,Devise::Models::RemoteAuthenticatable我假设我调用 remote_authenticatable.rb 并放入我的模型文件夹中的设计文件夹?

第二个文件,“Warden strategy for Devise”我不知道该叫什么,也不知道该放在哪里。

有任何想法吗?我发现教程很不完整。它链接到设计说明中作为执行此操作的方式。

编辑:

我一直在做更多的阅读,我不确定我是否需要按照该博客文章中所说的去做。我一直在尝试将数据简单地放入我的 Rails 应用程序,但无法正常工作。执行 PUT 请求会导致设计松散身份验证。

4

2 回答 2

6

我知道这个问题已有多年历史,但我也发现教程不完整,最近我花了几天时间尝试让远程身份验证工作。因此,我将提供我的解决方案,以防将来对某人有所帮助。我正在使用 Ruby 2.2.2 和 Rails 4.2.5.1。

首先,这个要点对我来说是一个非常有用的参考。

我还使用 gemfakeweb来模拟 API 调用。

这是我的文件的样子:

应用程序/模型/user.rb

class User < include ActiveModel::Model
  # required because some before_validations are defined in devise
  include ActiveModel::Validations
  # required to define callbacks
  extend ActiveModel::Callbacks
  # taken from http://stackoverflow.com/questions/8936906/whats-the-correct-way-to-make-before-validation-etc-work-in-an-activemodel
  include ActiveModel::Validations::Callbacks
  extend Devise::Models

  # create getter and setter methods internally for the fields below
  attr_accessor :email, :auth_token

  #required by Devise
  define_model_callbacks :validation

  devise :remote_authenticatable, :timeoutable

  # Latest devise tries to initialize this class with values
  # ignore it for now
  def initialize(options={})
  end
end

lib/models/remote_authenticable.rb

require 'fakeweb' #used for mocking API calls

module Devise
  module Models
    module RemoteAuthenticatable
      extend ActiveSupport::Concern

      #
      # Here you do the request to the external webservice
      #
      # If the authentication is successful you should return
      # a resource instance
      #
      # If the authentication fails you should return false
      #
      def remote_authentication(authentication_hash)

        FakeWeb.register_uri(:get, "http://localhost:3000/webservice/login.json",
                             :body => "{ \"success\": \"true\", \"auth_token\": \"secure_token_123\", \"email\": \"bob@1123.com\"}")

        # Your logic to authenticate with the external webservice
        response = Net::HTTP.get(URI.parse("http://localhost:3000/webservice/login.json"))

        self.email = JSON.parse(response)["email"]
        self.auth_token = JSON.parse(response)["auth_token"]
        return self
      end

      module ClassMethods
        ####################################
        # Overriden methods from Devise::Models::Authenticatable
        ####################################

        #
        # This method is called from:
        # Warden::SessionSerializer in devise
        #
        # It takes as many params as elements had the array
        # returned in serialize_into_session
        #
        # Recreates a resource from session data
        #
        def serialize_from_session(data, salt)
          resource = self.new
          resource.email = data['email']
          resource.auth_token = data['auth_token']
          resource
        end

        #
        # Here you have to return and array with the data of your resource
        # that you want to serialize into the session
        #
        # You might want to include some authentication data
        #
        def serialize_into_session(record)
          [
              {
                  :email => record.email,
                  :auth_token => record.auth_token
              },
              nil
          ]
        end

      end
    end
  end
end

config/initializers/remote_authenticable.rb

module Devise
  module Strategies
    class RemoteAuthenticatable < Authenticatable
      #
      # For an example check : https://github.com/plataformatec/devise/blob/master/lib/devise/strategies/database_authenticatable.rb
      #
      # Method called by warden to authenticate a resource.
      #
      def authenticate!
        #
        # authentication_hash doesn't include the password
        #
        auth_params = authentication_hash
        auth_params[:password] = password

        #
        # mapping.to is a wrapper over the resource model
        #
        resource = mapping.to.new

        return fail! unless resource

        # remote_authentication method is defined in Devise::Models::RemoteAuthenticatable
        #
        # validate is a method defined in Devise::Strategies::Authenticatable. It takes
        #a block which must return a boolean value.
        #
        # If the block returns true the resource will be logged in
        # If the block returns false the authentication will fail!
        #
        # resource = resource.remote_authentication(auth_params)
        if validate(resource){ resource = resource.remote_authentication(auth_params) }
          success!(resource)
        end
      end
    end
  end
end

配置/初始化程序/devise.rb

Devise.setup do |config|
  # ...
  # ...
  # OTHER CONFIGURATION CODE HERE
  # ...
  # ...

  # ==> Warden configuration
  # If you want to use other strategies, that are not supported by Devise, or
  # change the failure app, you can configure them inside the config.warden block.
  #
  # config.warden do |manager|
  #   manager.intercept_401 = false
  #   manager.default_strategies(scope: :user).unshift :some_external_strategy
  # end

  # BEGIN code that was added to this file
  config.warden do |manager|
    manager.strategies.add(:remote_authenticatable, Devise::Strategies::RemoteAuthenticatable)
    manager.default_strategies(:scope => :user).unshift :remote_authenticatable
  end

  Devise.add_module :remote_authenticatable, :controller => :sessions, :route => { :session => :routes }
  # END code that was added to this file

  # ...
  # ...
  # OTHER CONFIGURATION CODE HERE
  # ...
  # ...
end

配置/应用程序.rb

# ...
# ...
# OTHER CODE HERE
# ...
# ...

module RemoteAuth
  class Application < Rails::Application
    # ...
    # OTHER CODE HERE
    # ...

    # BEGIN code that was added to this file
    config.autoload_paths += Dir["#{config.root}/lib/**/"]
    config.autoload_paths += Dir["#{config.root}/app/models/**/"]
    # END code that was added to this file
  end
end
于 2016-02-17T18:27:01.113 回答
0

要点向您展示了如何做到这一点。还有一些额外的步骤,比如:token_authenticatable在你的用户模型中激活模块,以及config/devise.rb

于 2013-07-23T03:00:15.407 回答