咱们作程序的时候,加密解密是绕不开的话题,使用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原创文章