Ruby on rails 4 设计可锁定和自定义策略

Ruby on rails 4 设计可锁定和自定义策略,ruby-on-rails-4,authentication,devise,Ruby On Rails 4,Authentication,Devise,我正在为LDAP身份验证开发一个自定义策略,并且我已经实现了valid?和身份验证根据和本设计的方法。我的自定义策略本身就起作用 我还想使用该模块(以及其他Desive模块),但它们似乎只有在同时存在时才起作用。我一直在阅读Desive源代码,但我不明白Lockable是如何找到用户(资源)以增加:failed_尝试次数的。如何使用自定义策略将用户记录或资源传递给Lockable 下面是我的定制策略。我正在使用Desive 3.5和Rails 4.2 require 'net/ldap' req

我正在为LDAP身份验证开发一个自定义策略,并且我已经实现了
valid?
身份验证根据和本设计的方法。我的自定义策略本身就起作用

我还想使用该模块(以及其他Desive模块),但它们似乎只有在同时存在时才起作用。我一直在阅读Desive源代码,但我不明白Lockable是如何找到用户(资源)以增加:failed_尝试次数的。如何使用自定义策略将用户记录或资源传递给Lockable

下面是我的定制策略。我正在使用Desive 3.5和Rails 4.2

require 'net/ldap'
require 'devise/strategies/authenticatable'

module Devise
  module Strategies
   class LdapAuthenticatable < Authenticatable


  def valid?
    params[:user] && login.present? && password.present?
  end

  def authenticate!

    resource = mapping.to.find_for_authentication(email: params[:user][:email])

    if params[:user]
      begin
        ldap = Net::LDAP.new
        ldap.auth(my_ldap_service, my_ldap_service_password)
        ldap.encryption(:simple_tls)
        ldap.base = "base_here"
        ldap.host = my_ldap_host
        ldap.port = "636"
        result_attrs = ["employeenumber", "givenname", "sn", "mail", "department"] 

        result = ldap.bind_as(base: "base_here", filter: "(mail=#{login})", attributes: result_attrs, password: password, time: 3) 


        if result
          #valid ldap credentials
          user = get_user_from_database(result)
          if user
            success!(user)
          else
            fail!(:invalid_login)
          end

        else 
          fail!(:invalid_login)
        end

      rescue => e
        Rails.logger.error e.message
        fail!(:invalid_login)
      end

    end
  end

  def login
    params[:user][:email]
  end

  def password
    params[:user][:password]
  end

end
end
end
需要“net/ldap”
要求“设计/策略/可验证”
模块设计
模块策略
类LdapAuthenticatablee
Rails.logger.error e.消息
失败!(:无效的_登录)
结束
结束
结束
def登录
参数[:用户][:电子邮件]
结束
def密码
参数[:用户][:密码]
结束
结束
结束
结束

Active Directory应具有可锁定功能。通过在自定义策略中使用LDAP,您可以将该功能的责任从应用程序转移到LDAP/Active Directory。可锁定应该可以防止恶棍强行访问您的应用程序。如果Active Directory对此没有限制,他可以直接对其运行攻击,如果成功,可以使用应用程序中的凭据


但是,您应该使应用程序能够显示远程服务器返回的错误消息,如“重试次数太多,请在5分钟内重试”。

我最后将其与原始问题上发布的资源结合使用。要使可锁定工作,必须存在可验证的数据库。如果您可以控制LDAP,那么Toni的上述方法应该会起作用,我在提出问题时没有这样做。

您无法调用
验证
方法,该方法是您继承的可验证类的一部分。
validate
方法从可锁定模块调用
valid\u for\u authentication?
方法,然后该模块负责增加尝试次数并锁定帐户

在database_authenticatable中,通过使用返回布尔值的
valid_password?
解决此问题。在本例中,如果
bind_
不返回结果,则需要添加
validate(resource){false}

已修复的完整
身份验证方法如下所示

def authenticate!

    resource = mapping.to.find_for_authentication(email: params[:user][:email])

    if params[:user]
      begin
        ldap = Net::LDAP.new
        ldap.auth(my_ldap_service, my_ldap_service_password)
        ldap.encryption(:simple_tls)
        ldap.base = "base_here"
        ldap.host = my_ldap_host
        ldap.port = "636"
        result_attrs = ["employeenumber", "givenname", "sn", "mail", "department"] 

        result = ldap.bind_as(base: "base_here", filter: "(mail=#{login})", attributes: result_attrs, password: password, time: 3) 


        if result
          #valid ldap credentials
          user = get_user_from_database(result)
          if user
            success!(user)
          else
            fail!(:invalid_login)
          end

        else
          # no result -> wrong password
          validate(resource) { false }
          fail!(:invalid_login)
        end

      rescue => e
        Rails.logger.error e.message
        fail!(:invalid_login)
      end

    end
  end

“你找到解决这个问题的办法了吗?”拉维卡在下面看到了我的答案。