在建立使用者驗證機制時,通常我們會用 使用者名稱(Username), 電子信箱 (E-Mail) 及 密碼(Password) 來建立 User 表單。基於資安的保護,使用者在表單所填寫的密碼並不會直接儲存到資料庫內,而是先將密碼加密完成後的hash,再存到資料庫裡。

舉例來說:當使用者建立帳戶時所輸入的資訊

symbol1

再來看看 log 發生了什麼事? https://ithelp.ithome.com.tw/upload/images/20201006/20120868yVHMPkOxHE.png

注意看圖片內最後一行就是把密碼加密成為 “$2a$12…zv706” 後再存入資料庫裡,這其中的魔法就是 BCrypt gem 幫我們做的好事。

BCrypt 提供 rails 開發者 has_secure_password 方法來做單向隨機加密及驗證在指定的 password_digest 欄位。順便一提,當使用 has_secure_password 方法時,會自動附帶3個驗證:

1) 檢查密碼是否存在,

2) 密碼長度必須是不大於72 bytes,

3) 確認密碼填寫是否正確 (using a XXX_confirmation attribute)

貼心的 Rails 在 Gemfile 裡已有提供 BCrypt gem 來做加密和驗證功能。 設定上還蠻容易的,在 user model 裡加上 has_secure_password 以及新增一個名為 password_digest 的欄位在 users table 就可以有加密的效果了!

當需要驗證密碼時提供了authenticate 的方法來做解密的動作。例如:user.authenticate(‘password’)這邊在使用 has_secure_password 時要注意使用的Rails版本。

在 Rails 6.0 之前,has_secure_password 機制只接受一種屬性(attribute) 設定為 password_digest,因此表格的密碼欄位名稱都必須是password_digest。而在 Rails 6.0之後,has_secure_password允許可以自訂名稱的選項 ,也就是自訂欄位名稱+底線+digest (column_name_digest)。 https://ithelp.ithome.com.tw/upload/images/20201006/20120868QSEgJYDSSE.png

接著我們可以來到 rails console 測試一下 https://ithelp.ithome.com.tw/upload/images/20201006/20120868SvehEvWjjI.png

從 rails console 可以看出,只有當authenticate拿到正確的密碼時,解密後才可以取得使用者 jeff 的資料了。

參考資料: