关于设计可锁定的第n次尝试的自定义消息

时间:2017-05-16 14:27:09

标签: ruby-on-rails ruby devise

我正在寻找一种方法来为设计可锁定模块中的各种失败尝试显示自定义消息。

我发现默认情况下只会通知最后一次尝试: https://github.com/plataformatec/devise/blob/master/lib/devise/models/lockable.rb#L121

是否有任何优雅的方式来显示第7次和第8次失败尝试的不同警告信息?你能提出一个吗?

3 个答案:

答案 0 :(得分:1)

您可以使用以下方式覆盖Devise代码

module Devise::Models::Lockable
  def unauthenticated_message
    # If set to paranoid mode, do not show the locked message because it
    # leaks the existence of an account.
    if Devise.paranoid
      super
    elsif access_locked? || (lock_strategy_enabled?(:failed_attempts) && attempts_exceeded?)
      :locked
    elsif lock_strategy_enabled?(:failed_attempts) && last_attempt? && self.class.last_attempt_warning
      :last_attempt
    else
      return "invalid_fail_attempt_#{failed_attempts}" if temporary
      #super normally this would return :invalid see super class
    end
  end
end

然后您需要添加翻译内容

devise.failure.user.invalid_1: "one shot down! 4 to go"
devise.failure.user.invalid_2: "ooh 2 strikes!!"
devise.failure.user.invalid_3: "3 strikes!! but your not out yet! 2 left"

您并不需要数字4,因为last_attempt?上运行的代码块会处理数字4(假设您的尝试次数限制为5,请根据需要进行调整。)

该代码也可能在超类中出现在任何地方。

答案 1 :(得分:0)

也许是一个自定义的SessionsController,我猜这个设计使用动态方法,我无法找到:调用last_attempt只是覆盖unauthenticated_message方法

def create
    if self.resource.failed_attempts != self.resource.class.maximum_attempts - 1 and self.resource.failed_attempts != 0
        attempts_left = self.resource.failed_attempts
        flash[:alert] = I18n.t 'some_path.errors.attempts', attempts_left: attempts_left
    super
end

想法是在最大尝试次数为1次或更少时添加闪光警报,在最大尝试次数和最后一次尝试的情况下,您将获得默认消息

答案 2 :(得分:0)

这个想法很有意思,但由于在lockable之前调用create而无法工作,所以我创建了一个我在create之前调用的自定义操作。

这对我有用:

class User::SessionsController < Devise::SessionsController
  before_action :check_failed_attempts, only: :create

  def after_sign_in_path_for(user)
    # some code
  end

  def create
    super
    # create some stuff and check others
  end

  def destroy
    # may be destroy and deal with cookies
    super
  end

  def check_failed_attempts
    flash.clear

    email = self.params["user"]["email"]
    return unless email

    user = User.find_by_email(email)
    return unless user

    failed_attempts = user.failed_attempts
    maximum_attempts = User.maximum_attempts
    attempts_left = maximum_attempts - failed_attempts - 1
    if attempts_left != maximum_attempts and attempts_left > 1
      flash[:notice] = I18n.t 'devise.failure.n_attempt', attempts_left: attempts_left
    end
  end
end