【问题标题】:Custom message on devise lockable n-th attempt关于设计可锁定第 n 次尝试的自定义消息
【发布时间】:2017-05-16 14:27:09
【问题描述】:

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

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

有没有什么优雅的方法可以为第 7 次和第 8 次失败的尝试显示不同的警告消息?你能推荐一个吗?

【问题讨论】:

    标签: ruby-on-rails ruby devise


    【解决方案1】:

    你可以用

    覆盖设计代码
    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? 上运行的块处理(假设您有 5 次尝试限制,请根据需要进行调整。)

    该代码也可能放在超类中的任何位置..

    【讨论】:

      【解决方案2】:

      这个想法很有趣,但行不通,因为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
      

      【讨论】:

        【解决方案3】:

        也许是一个自定义的 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 次或少于最大尝试次数时添加一个闪光警报,在最大尝试次数和最后一次尝试次数的情况下,您将收到默认消息

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-25
          • 1970-01-01
          • 1970-01-01
          • 2019-12-15
          • 1970-01-01
          • 2017-06-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多