铁轨上的红宝石-Lockable在Devise不起作用



我已经在两个用户帐户Admin和Customer上实现了Devise。注册sign_in函数运行良好。我正在尝试在管理员帐户上实现可锁定。我使用的是Devise 3.2.4。

在特定时间内输入错误凭据后,帐户仍然处于活动状态,并且不会记录失败的尝试次数。

我已在此处遵循本指南

我的设备.rb:

Devise.setup do |config|
  config.secret_key = 'XXXXX_the_secret_key_XXXXXXX'
  config.mailer_sender = 'mymail@domain.com'
  require 'devise/orm/active_record'
  # config.authentication_keys = [ :email ]
  # config.request_keys = []
  config.case_insensitive_keys = [ :email ]
  config.strip_whitespace_keys = [ :email ]
  # config.params_authenticatable = true
  # config.http_authenticatable = false
  # config.http_authenticatable_on_xhr = true
  # config.http_authentication_realm = 'Application'
  # config.paranoid = true
  # passing :skip => :sessions to `devise_for` in your config/routes.rb
  config.skip_session_storage = [:http_auth]
  # config.clean_up_csrf_token_on_authentication = true
  config.stretches = Rails.env.test? ? 1 : 10
  # config.pepper = '38635688e9d775b28e8da07b695dfced7b3bd4899c0a9a2a0f9b5ed5a8113e79864f76039166f827ef0134452fc0080f279adc4d1724362e079d0af3361edaf5'
  # config.allow_unconfirmed_access_for = 2.days
  # config.confirm_within = 3.days
  config.reconfirmable = true
  # config.confirmation_keys = [ :email ]
  # config.remember_for = 2.weeks
  # config.extend_remember_period = false
  # config.rememberable_options = {}
  # Range for password length.
  config.password_length = 8..128
  # config.email_regexp = /A[^@]+@[^@]+z/
  # config.timeout_in = 30.minutes
  # config.expire_auth_token_on_timeout = false
  # :failed_attempts = Locks an account after a number of failed attempts to sign in.
  # :none            = No lock strategy. You should handle locking by yourself.
  config.lock_strategy = :failed_attempts
  # Defines which key will be used when locking and unlocking an account
  config.unlock_keys = [ :email ]
  # config.unlock_keys = [ :time ]
  config.unlock_strategy = :both
  # config.unlock_strategy = :time
  config.maximum_attempts = 3
  config.unlock_in = 2.hour
  # config.last_attempt_warning = false
  config.reset_password_within = 24.hours
  # config.encryptor = :sha512
  config.sign_out_via = :delete
end

我的管理员模型:

class Admin < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :lockable
end

我的迁移添加可锁定管理员:

class AddLockableToAdmin < ActiveRecord::Migration
  def change
    add_column :admins, :failed_attempts, :integer, default: 0
    add_column :admins, :unlock_token, :string
    add_column :admins, :locked_at, :datetime
  end
end

我的路线.rb:

devise_for :admins

步骤1:验证设备是否正确安装

1-迁移的failed_attempts字段中缺少null: false

add_column :admins, :failed_attempts, :integer, default: 0, null: false

修复它并重新运行迁移

2-更新控制台中的所有现有记录:

Admin.update_all failed_attempts: 0

3-关闭您的服务器、控制台和任何其他使用或预加载您的应用程序的设备(spring、zeus等)

4-在rails控制台中,验证设备是否正确安装

Admin.new.respond_to? :failed_attempts应返回真实

5-仍然在控制台中,验证Admin是否可以手动锁定:

Admin.first.lock_access!

您应该看到SQL正在更新记录的locked_atunlock_token字段

6-启动服务器并再次输入错误的密码(使用您手动锁定的另一个用户),查看failed_attempts的值是否更改

=>结果:所有工作,但使用错误凭据登录不会增加failed_attempts


第2步:验证设计失败的地方

强力调试

我不知道你是否有调试器,所以我们将临时编辑负责递增failed_attempts的方法,看看它在哪里停止。在designgem中打开文件"lib/devert/models/locked.rb",然后像这样编辑:

def valid_for_authentication?
  puts 'mark 1'
  return super unless persisted? && lock_strategy_enabled?(:failed_attempts)
  puts 'mark 2'
  # Unlock the user if the lock is expired, no matter
  # if the user can login or not (wrong password, etc)
  unlock_access! if lock_expired?
  if super && !access_locked?
    puts 'mark 3 (you should not see me)'
    true
  else
    puts 'mark 4 (you are supposed to see me)'
    self.failed_attempts ||= 0
    self.failed_attempts += 1
    if attempts_exceeded?
      puts 'mark 5 (you should not see me)'
      lock_access! unless access_locked?
    else
      puts 'mark 6 (you are supposed to see me)'
      save(validate: false)
    end
    false
  end
end

正如你所看到的,我添加了"标记"来查看执行过程。注意,根据你的设计版本,方法的内容可能略有不同,你只需要添加"标记"。

重新启动服务器,尝试使用不正确的凭据登录,然后查看控制台以查看显示的标记。

在我们的测试之后,您可以恢复此文件以删除标记

=>结果:使用错误凭证登录时,控制台中不会显示任何标记

在控制台Admin.first.valid_for_authentication? 中执行

=>结果:显示标记1、2、4、6,并在数据库中递增failed_attempts


解决方案(有待确认)

用于验证的表单具有不重定向到设备控制器的action值。您似乎正在使用api_console来生成用于身份验证的表单。

听从Benj的建议后,我没能让它发挥作用。调试lib/devert/models/locked.rb时,代码进入if super && !access_locked?条件。

事实证明,我的问题是在登录过程中,我错误地使用了valid_for_authentication?函数。也就是说,我做了一个类似的检查:

if user.valid_for_authentication? && user.valid_password?(params[:password])

而不是在块中提供密码验证:

if user.valid_for_authentication? { user.valid_password?(params[:password]) }

我也遇到了同样的问题。但我通过这些步骤解决了

  1. 运行rails g migration add_lockable_to_depevice

  2. 在db/migrate/***********_add_lockable_to_devie 中添加以下代码

    def up
     add_column :users, :failed_attempts, :integer
     add_column :users, :unlock_token, :string
     add_column :users, :locked_at, :datetime
     add_index :users, :unlock_token, unique: true
     execute("UPDATE users SET confirmed_at = NOW()")
    end
    def down
      remove_columns :users, :failed_attempts, :unlock_token, :locked_at  
    end
    

3.之后运行rake db:migrate

不要忘记步骤3

我遇到了类似的问题,我用这次迁移重新创建了表。

试试这个:

change_table(:admins) do |t|
  t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both
end

这是一个棘手的案例,我帮不了你什么,但可以指导你自助。

Devise在更新失败尝试计数https://github.com/plataformatec/devise/blob/master/lib/devise/models/lockable.rb行号92。

def valid_for_authentication?
    return super unless persisted? && lock_strategy_enabled?(:failed_attempts)
    # Unlock the user if the lock is expired, no matter
    # if the user can login or not (wrong password, etc)
    unlock_access! if lock_expired?
    if super && !access_locked?
      true
    else
      self.failed_attempts ||= 0
      self.failed_attempts += 1
      if attempts_exceeded?
        lock_access! unless access_locked?
      else
        save(validate: false)
      end
      false
    end
  end

您必须编辑已安装的gem的相应文件,并在stdout中添加一个记录器或执行put,以查看else循环是否执行。唯一可能的原因是当第一行返回被调用时。

我认为如果不深入研究设计代码,你就无法解决这个问题,因为你的配置是正确的。

相关内容

  • 没有找到相关文章