本文翻譯自 APP_KEY And You
可能每個 Laravel 開發者新建或者克隆一個 Laravel 程式的時候,composer install
之後最可能以及最重要的的第一步操作就是生成 APP_KEY
。
在這篇文章中我們會討論APP_KEY
能做的和不能做的,有些人會把使用者密碼的雜湊處理與APP_KEY
相關聯(實際上它們毫無關聯)。
什麼是 APP_KEY
每一個 Laravel 程式都會生成一個隨機的32位長度的字串儲存在.env
檔案中的APP_KEY
鍵值中,當我們新建 Laravel 專案的時候會自動為你建立一個,只有在克隆的時候你才有可能發現它沒有被設定。
你可能看到過下面的錯誤,說明APP_KEY
沒有設定
你可以自己手動生成或者使用 php artisan key:generate
來進行建立 APP_KEY
。
當你的應用程式執行的時候,只有一個地方會用到APP_KEY
:cookies。Laravel 使用它來加密所有的cookies,在將cookie返回給使用者之前 Laravel 會對 cookie進行加密,然後再返回給使用者,這樣客戶端就無法自己修改cookie來偽裝成管理員或者其他使用者了。
所以的加密和解密都在 Encrypter
中進行處理,其中主要使用了 [openssl_encrypt](https://secure.php.net/manual/en/function.openssl-encrypt.php)
進行加密。
有很多使用者都會有一個誤解,那就是APP_KEY
是用來處理使用者雜湊密碼的。事實上不是這樣的。Laravel的密碼使用了 Hash::make()
或者 bcrypt()
來進行雜湊處理,其中並沒有用到APP_KEY
。
加密 VS 雜湊
在 Laravel 中有兩個主要的加密 Facade,分別是 Crypt
(對稱加密) 和 Hash
(單向加密雜湊)。密碼是雜湊,而cookie則是對稱加密。
對稱加密
假設我想傳送一條加密的資訊給我的好友A。我們商議好了一個用於加密和解密的key:
$key = "dont-panic";
當我想要傳送一條只有上面的key能解鎖的資訊時,我們可以使用openssl_encrypt()
(Laravel 的 Crypt
也是使用的這個方法),具體如下:
$message = "So long and thanks for all the fish";
$key = "dont-panic";
$cipher = "AES-256-CBC";
echo openssl_encrypt($message, $cipher, $key);
// JJEK8L4G3BCfY0evXDRxUke2zqAzq6i7wL/Px4SjaEHXqt3x7hsj4+PhVQaH4ujX
此時,你就可以把這段加密的程式碼傳送給A,然後他可以進行解密了。
$secret = "JJEK8L4G3BCfY0evXDRxUke2zqAzq6i7wL/Px4SjaEHXqt3x7hsj4+PhVQaH4ujX";
$key = "dont-panic";
$cipher = "AES-256-CBC";
echo openssl_decrypt($secret, $cipher, $key);
// So long and thanks for all the fish
Laravel的cookie加密解密也是同理,只不過key使用的是APP_KEY
。
單向雜湊
當我們使用密碼的時候,我們應當從不使用對稱加密的方法,來避免使用者可能解密密碼。這表示Crypt
無法勝任,因此我們需要使用雜湊方法,具有如下的特點:
- 快速:計算機能夠快速的生成雜湊值
- 確定性:針對同樣的輸入,輸出是固定的
- 隨機性:即使只更改一位字串,雜湊之後的輸出應該十分不同
- 唯一性:碰撞概率應該非常非常的小
- 難於被暴力破解: 雜湊之後的值應當難以被暴力破解
你應當聽說過許多的單向雜湊演算法,例如md5
和 SHA-1
。在Laravel中使用了PHP的原生方法password_hash()
,它使用的雜湊演算法叫bcrypt
。
use Illuminate\Support\Facades\Hash;
$password = "dont-panic";
echo Hash::make($password);
// $2y$10$hEEF0lv4spxnvw5O4XyLZ.QjCE1tCu8HjMpWhmCS89J0EcSW0XELu
如果你曾經檢視過users
資料表,那麼上面的輸出你可能會似曾相識。下面解釋一下其中的含義:
$2y$
表示我們使用了blowfish
演算法(bcrypt)10$
表示演算法使用的 cost(值越高表示生成雜湊的時間越長)hEEF0lv4spxnvw5O4XyLZ.
表示一個22位的隨機“鹽”QjCE1tCu8HjMpWhmCS89J0EcSW0XELu
雜湊結果
由於這是一個單向雜湊,因此我們無法進行解密,我們能做的只是去驗證其是否匹配。
use Illuminate\Support\Facades\Hash;
$input = request()->get('password'); // "dont-panic"
$hash = '$2y$10$hEEF0lv4spxnvw5O4XyLZ.QjCE1tCu8HjMpWhmCS89J0EcSW0XELu';
return Hash::check($input, $hash);
// true
因此我們可以看到,在對稱加密中我們使用到了APP_KEY
,而在密碼雜湊的時候我們是不需要使用它的。
總結
- 更改
APP_KEY
不會使使用者的密碼失效 - 更改
APP_KEY
會使session 和 cookie 失效,導致當前已登入使用者退出登入 - 不要害怕你的
APP_KEY
- 如果你在其他地方使用了Laravel的加密方法,那麼你需要制定一個計劃來應對
APP_KEY
的更改