【问题标题】:Update user without hashing twice password更新用户而不散列两次密码
【发布时间】:2014-03-05 22:24:44
【问题描述】:

我的模特:

class User < Sequel::Model
self.raise_on_save_failure = false
plugin :validation_helpers
def validate
    super
    validates_format /@/, :email
    validates_presence [:email, :password]
    validates_unique :email
end

def before_save
    super
    self[:password] = BCrypt::Password.create(self[:password])
end

结束

但是当我更新用户时,我的密码哈希两次。我知道这是因为before_save 挂钩,但我想保留sequel 验证(validates_presence)真实密码,而不是bcrypt 哈希的结果(因为BCrypt::Password.create('') 不为空)

所以我需要以某种方式做下一步:

  1. 检查密码是否更改
  2. 通过sequel验证真实密码
  3. 保存我的密码的 bcrypt 哈希

【问题讨论】:

    标签: ruby sinatra sequel bcrypt-ruby


    【解决方案1】:

    我认为你应该重新考虑你的工作流程。如果您希望仅在尝试更新数据库时捕获无效输入,为什么不这样做:

    post '/update' do
      ...
    
      if params[:password] == nil || params[:password].empty?
        password = nil
      else
        password = BCrypt::Password.create(params[:password])
      end
    
      # I have no idea how this line should really look like in your code
      User.find(param[:id]).set(:password, password)
    
      ...
    end
    

    所以基本上,如果密码字段未发送或为空,则将其设为 nil。

    正如 iain 在 cmets 中非常清楚地指出的那样:

    [...] 您应该只使用 Sequel 来验证数据库已经或将要保存的数据。真正的密码应该由业务逻辑层验证,这就是这个答案中发生的事情。

    【讨论】:

    • 谢谢,但你 set 到 DB 哈希密码。所以 Sequel 模型将验证哈希,而不是真正的密码,就像使用钩子 (before_save) 一样。你的提示没问题,如果我只需要validates_presence,但我们也应该手动验证最小/最大长度。我不知道在这种情况下是否可以使用 Sequel 验证助手。
    • @bravedick 从可用的钩子列表here 看起来你最好使用before_create 而不是before_save
    • @bravedick 我认为这是正确的答案,因为您应该只使用 Sequel 来验证 由数据库保存或将保存的数据。真正的密码应该由业务逻辑层验证,这就是这个答案中发生的事情。来自Why Validations?“验证主要用于将错误消息与模型上的特定属性相关联以显示给用户”。
    【解决方案2】:

    您可以像这样在类方法中检查它:

      if user.password_digest != expected_password
        user = nil
      end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-10
      • 2020-12-20
      • 1970-01-01
      • 2016-03-23
      • 1970-01-01
      • 2019-05-31
      • 2015-11-18
      • 1970-01-01
      相关资源
      最近更新 更多