咱們作程序的時候,加密解密是繞不開的話題,使用yii2開發應用的時候,都內置了哪些有關加密解密(安全)方便的支持那?本文將爲你揭曉。
相關環境php
在yii2中,管理加密解密的庫叫作Security,它以yii2組件的形式存在,所以你能夠經過Yii::$app->security來獲取並使用它。html
Security組件源代碼位置以下算法
vendor/yiisoft/yii2/base/Security.php
Security組件一共有15個與加密解密(&編碼)相關的公共方法,咱們先來列一個清單。安全
我想有一些你必定沒見過,不要緊,咱們一一去了解。yii2
之因此先說generateRandomString是由於它最經常使用,起碼我是這樣。app
public function generateRandomString($length = 32){...}
生成一個隨機的字符串,參數$length表明這個字符串的長度,默認32位。值得說明的是這個字符串的取值爲範圍是[A-Za-z0-9_-]。dom
generatePasswordHash & validatePassword常常被用來加密用戶密碼以及對密碼是否正確的驗證,自從MD5可能被碰撞後,咱們用yii2開發應用的時候,generatePasswordHash函數對密碼進行加密就成爲首選了,它調用了crypt函數。yii
通常用法以下函數
// 使用generatePasswordHash爲用戶的密碼加密,$hash存儲到庫中 $hash = Yii::$app->getSecurity()->generatePasswordHash($password); // 使用validatePassword對密碼進行驗證 if(Yii::$app->getSecurity()->validatePassword($password, $hash)){ // 密碼正確 }else{ // 密碼錯誤 }
和generateRandomString相似,生成一個隨機的串,參數爲長度,默認爲32位,區別在於generateRandomKey生成的不是ASCII。this
簡單的說 generateRandomString 約等於 base64_encode(generateRandomKey)。
編碼和解碼函數,使用一個祕鑰對數據進行編碼,而後經過此祕鑰在對編碼後的數據進行解碼。
例子
$dat = Yii::$app->security->encryptByPassword("hello","3166886"); echo Yii::$app->security->encryptByPassword($dat,"3166886");// hello
要注意,經過上面獲得的編碼後的數據不是ASCII,能夠經過base64_encode和base64_decode在外層包裝下。
一樣是一組編碼和解碼函數,比經過密碼的方式要快。函數聲明爲
public function encryptByKey($data, $inputKey, $info = null){} public function decryptByKey($data, $inputKey, $info = null){}
encryptByKey & decryptByKey 存在着第三個參數,好比咱們能夠傳遞會員的ID等,這樣此信息將和$inputKey一塊兒做爲加密解密的鑰匙。
使用標準的 HKDF 算法從給定的輸入鍵中導出一個鍵。在PHP7+使用的是hash_hkdf方法,小於PHP7使用hash_hmac方法。
使用標準的 PBKDF2 算法從給定的密碼導出一個密鑰。該方法能夠用來進行密碼加密,不過yii2有更好的密碼加密方案 generatePasswordHash。
有的時候爲了防止內容被篡改,咱們須要對數據進行一些標記,hashData和validateData就是完成這個任務的組合。
hashData 用來對原始數據進行加數據前綴,好比以下代碼
$result = Yii::$app->security->hashData("hello",'123456',false); // ac28d602c767424d0c809edebf73828bed5ce99ce1556f4df8e223faeec60eddhello
你看到了在hello的前面多了一組字符,這組字符會隨着原始數據的不一樣而變化。這樣咱們就對數據進行了特殊的防止篡改標記,接下來是validateData上場了。
注意:hashData的第三個參數表明生成的哈希值是否爲原始二進制格式. 若是爲false
, 則會生成小寫十六進制數字.
validateData 對已經加了數據前綴的數據進行檢測,以下代碼
$result = Yii::$app->security->validateData("ac28d602c767424d0c809edebf73828bed5ce99ce1556f4df8e223faeec60eddhello",'123456',false); // hello
若是返回了原始的字符串則表示驗證經過,不然會返回假。
validateData 函數的第三個參數應該與使用 hashData() 生成數據時的值相同. 它指示數據中的散列值是不是二進制格式. 若是爲false
, 則表示散列值僅由小寫十六進制數字組成. 將生成十六進制數字.
可防止時序攻擊的字符串比較,用法很是簡單。
Yii::$app->security->compareString("abc",'abc');
結果爲真則相等,不然不相等。
那麼什麼是時序攻擊那?我來舉一個簡單的例子。
if($code == Yii::$app->request->get('code')){ }
上面的比較邏輯,兩個字符串是從第一位開始逐一進行比較的,發現不一樣就當即返回 false,那麼經過計算返回的速度就知道了大概是哪一位開始不一樣的,這樣就實現了電影中常常出現的按位破解密碼的場景。
而使用 compareString 比較兩個字符串,不管字符串是否相等,函數的時間消耗是恆定的,這樣能夠有效的防止時序攻擊。
maskToken用於掩蓋真實token且不能夠壓縮,同一個token最後生成了不一樣的隨機令牌,在yii2的csrf功能上就使用了maskToken,原理並不複雜,咱們看下源碼。
public function maskToken($token){ $mask = $this->generateRandomKey(StringHelper::byteLength($token)); return StringHelper::base64UrlEncode($mask . ($mask ^ $token)); }
而unmaskToken目的也很明確,用於獲得被maskToken掩蓋的token。
接下來咱們看一個例子代碼
$token = Yii::$app->security->maskToken("123456"); echo Yii::$app->security->unmaskToken($token);// 結果爲 123456
最後咱們總結下
更多Yii原創文章