Ruby on Rails: Why does the user's encrypted password get changed in the DB when I use the “toggle” method on the admin attribute?

前端 未结 3 820
时光说笑
时光说笑 2021-01-07 04:28

I just finished Hartl\'s Rails Tutorial book and I\'m using his account authentication logic in my first rails app. However, when I make a new user account and set it as an

相关标签:
3条回答
  • 2021-01-07 04:40

    try to change your before_save method:

    def encrypt_password
      if password.present?
        self.salt = make_salt if new_record?
        self.encrypted_password = encrypt(password)
      end
    end
    

    UPD. or you can make it little shorter

    def encrypt_password
      self.salt = make_salt if new_record?
      self.encrypted_password = encrypt(password) if password.present?
    end
    
    0 讨论(0)
  • 2021-01-07 04:42

    Not sure what is going on specifically. Could be that the password is getting encrypted again using a different salt (which is based on the time). Try adding debugger to the first line of encrypt_password and then run the same code from the console to see if the password is getting encrypted when you run toggle!

    0 讨论(0)
  • 2021-01-07 04:46

    There's something odd going on in your code. A salt should be independent of the password, but your (Hartl's?) make_salt method says:

    def make_salt
      secure_hash("#{Time.now.utc}--#{password}")      
    end
    

    This might have been the source of your nil problem, since you were accessing password inside make_salt; in any case this is bad crypto since it amounts to using Time.now as a "random" salt, which is much easier to crack (build rainbow tables for).

    You should instead be using a good random number generator, e.g. Ruby's built-in SecureRandom:

    def make_salt
      SecureRandom.hex(64)
    end
    

    Why such a long salt? According to https://crackstation.net/hashing-security.htm, "To make it impossible for an attacker to create a lookup table for every possible salt, the salt must be long. A good rule of thumb is to use a salt that is the same size as the output of the hash function. For example, the output of SHA256 is 256 bits (32 bytes), so the salt should be at least 32 random bytes." I don't want to use SecureRandom.random_bytes(32) to avoid potential database string encoding problems with non-ascii characters, and 64 random hex characters comprise 32 random bytes, which I think counts as the same entropy.

    0 讨论(0)
提交回复
热议问题