【最佳實務系列】PHP 開發人員如何做好密碼保護 & Laravel 底層密碼儲存和驗證實現

來源:互聯網
上載者:User
隨著線上攻擊的增多,密碼安全越來越重要。作為開發人員我們要擔負起安全管理、計算雜湊和儲存使用者密碼的責任,不管應用是簡單的遊戲還是絕密商業檔案的倉庫,都要做到這一點。PHP內建了一些工具,讓保護密碼變得更加容易,本節我們就來討論如何根據現代的安全措施來使用這些工具。

1、密碼保護三原則

絕對不能知道使用者的密碼

我們絕對不能知道使用者的密碼,也不能有擷取使用者密碼的方式,如果應用的資料庫被黑,你肯定不希望資料庫中有純文字或能解密的密碼。任何時候,知道的越少越安全。

絕對不要約束使用者的密碼

如果要求密碼符合特定的模式,其實是為不懷好意的人提供了攻擊應用的途徑,如果必須約束密碼,我建議只限制最小長度,把常用的密碼或基於字典建立的密碼加入黑名單也是好主意。

絕對不能通過電子郵件發送使用者密碼

如果你通過電子郵件給使用者發送密碼,使用者會知道三件事:你知道他的密碼,你使用純文字或能解密的方式儲存了他的密碼,你沒有對通過互連網發送純文字的密碼感到不安。

我們應該在電子郵件中發送用於設定或修改密碼的URL,Web應用通常會產生一個唯一的令牌,這個令牌只在設定或修改密碼時使用一次(比如修改密碼),通常我們把這個令牌作為設定或修改密碼URL的一個參數,當使用者訪問這個URL時,應用會驗證令牌是否有效,如果有效則繼續操作,操作完成後,令牌失效,不能重複使用。

2、密碼儲存演算法

關於密碼儲存的最佳實務是計算密碼的雜湊值,而不是加密使用者的密碼。加密和雜湊不是一回事,加密事雙向演算法,加密的資料可以解密,而雜湊是單向演算法,雜湊後的資料不能再還原成原始值,而且相同的資料得到的雜湊值始終相同。

在資料庫中儲存使用者的密碼,要先計算密碼的雜湊值,然後在資料庫中儲存密碼的雜湊值,如果駭客攻入資料庫,只能看到無意義的密碼雜湊值,需要花費大量的時間和NSA資源才能破解。

雜湊演算法有很多種(如md5、SHA1、bcrypt和scrypt),有些演算法速度很快,用於驗證資料完整性;有些演算法的速度則很慢,旨在提高安全性。產生密碼和儲存密碼時要使用速度慢、安全性高的演算法。

目前,最安全的演算法當屬bcrypt,與md5和SHA1不同,bcrypt故意設計得很慢,bcrypt會自動加鹽(salt),防止潛在的彩虹表攻擊,bcrypt演算法會花費大量時間反覆處理資料,產生特別安全的雜湊值。在這個過程中,處理資料的次數叫工作因子,工作因子的值越高,破解密碼所需的時間越長,安全性越好。bcrypt演算法永不過時,如果電腦運算速度變快了,我們只需提高工作因子的值。

3、密碼雜湊API

通過前面的介紹,我們知道在處理使用者的密碼時要考慮很多東西,好在PHP 5.5.0原生的雜湊API( http://php.net/manual/zh/book.password.php )提供了很多便於使用的函數,大大簡化了計算密碼雜湊值和驗證密碼的操作,而且,這個密碼雜湊API預設使用bcrpt演算法。

開發Web應用時,有兩個地方會用到密碼雜湊API:註冊使用者和使用者登入,下面我們以Laravel提供的使用者註冊和登入狀態例,看看PHP密碼雜湊API時如何簡化這兩個操作的。

註:Laraval架構內建的使用者註冊和登入功能正是使用了PHP雜湊API實現密碼的儲存和驗證。

註冊使用者

使用者註冊在 AuthController 中完成,新使用者的建立在該控制器的 create 方法中實現:

可以看到這裡使用了Laravel提供的輔助函數 bcrypt 對使用者提交的密碼進行雜湊並儲存到資料庫。 bcrypt 函數定義如下:

這裡我們可以看出實際上是調用了別名為 hash 的服務提供者執行個體上的 make 方法實現雜湊密碼,進入 HashServiceProvider ,在 register 方法中我們可以看到 hash 對應的類為 BcryptHasher ,在該類中我們找到了 make 方法:

這裡的核心是調用了PHP提供的 password_hash 函數,該函數接收三個參數,第一個是使用者輸入的密碼值,第二個參數是使用的雜湊演算法(更多演算法查看: http://php.net/manual/zh/password.constants.php ),第三個參數可選,包括 salt 和 cost 兩個選項,分別表示幹擾字串(加鹽)和前面提到的工作因子,工作因子可以隨著硬體效能的提升而提升,不傳的話使用隨機加鹽和預設工作因子(計算雜湊值一般需要0.1~0.5s)。如果計算失敗,拋出異常。

使用者登入

在Larval中以在 auth.php 中使用session作為guards、eloquent作為providers實現使用者登入認證為例(實際上預設設定就是這樣),登入驗證最終會走到 EloquentUserProvider 的 validateCredentials 方法:

$this->hasher 對應的實現也是 BcryptHasher 類,我們來查看它的 check 方法:

其中傳入的第一個參數是使用者輸入的密碼,第二個參數是使用者註冊時儲存的密碼雜湊值,如果雜湊值為空白直接返回false,否則調用php提供的 password_verify 函數,該函數用於驗證密碼(純文字)和雜湊值是否匹配,匹配返回true,否則返回false。

重新計算雜湊值

通過上述步驟使用者已經可以實現登入認證了,但是登入前我們還需要檢查現有的密碼雜湊值是否已經到期,如果到期,需要重新計算密碼雜湊值。

為什麼要重新計算呢?加入我們的應用建立於兩年前,那時候使用的工作因子時10,現在使用的是20,因為電腦的速度更快了,駭客也更聰明了。可以有些使用者的密碼雜湊值仍然是工作因子為10時產生的,這時,登入認證通過後,要使用 password_needs_refresh 函數檢查使用者記錄中現有的雜湊值是否需要更新,這個函數可以確保指定的密碼雜湊值是使用最新的雜湊演算法建立的。如果確實需要重新計算產生密碼的雜湊值,要使用 make 方法產生新的雜湊值並更新資料庫中的原密碼。

Laraval中目前並沒有使用這一功能,但是在 BcryptHasher 類中已經提供了對應的函數:

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.