我已在两个用户帐户Admin和Customer上实现了Devise.注册sign_in函数工作正常.我正在尝试在管理员帐户上实现可锁定.我正在使用Devise 3.2.4.
在特定时间输入错误凭据后,该帐户仍处于活动状态,并且不会记录failed_attempts.
我在这里遵循了这个指南.
我的设计.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
我的routes.rb:
devise_for :admins
Benj.. 5
第1步:验证设备是否正确安装
1 -你缺少null: false
在failed_attempts
迁移的领域.
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_at
和unlock_token
记录的字段
6-启动服务器并再次尝试输入错误的密码(使用其他手动锁定的用户),查看failed_attempts
更改的值
=>结果:所有工作,但使用错误的凭据登录不会增加 failed_attempts
第2步:验证设计失败的位置
暴力调试
我不知道你是否有调试器,所以我们暂时编辑负责递增的方法failed_attempts
,并查看它停止的位置.在devise gem中打开文件"lib/devise/models/lockable.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
它生成用于身份验证的表单.
第1步:验证设备是否正确安装
1 -你缺少null: false
在failed_attempts
迁移的领域.
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_at
和unlock_token
记录的字段
6-启动服务器并再次尝试输入错误的密码(使用其他手动锁定的用户),查看failed_attempts
更改的值
=>结果:所有工作,但使用错误的凭据登录不会增加 failed_attempts
第2步:验证设计失败的位置
暴力调试
我不知道你是否有调试器,所以我们暂时编辑负责递增的方法failed_attempts
,并查看它停止的位置.在devise gem中打开文件"lib/devise/models/lockable.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
它生成用于身份验证的表单.