当前位置: 首页 > 后端技术 > PHP

记录一个敏感信息脱敏过程

时间:2023-03-29 15:28:08 PHP

背景:刚进A公司的时候,老板让我做数据脱敏。通过调用运维团队的数据脱敏接口,保证用户的敏感信息不会泄露。公司项目主要使用laravel5.1和YII1.1版本。具体解决方案:敏感信息字段的调用存在于代码的各个角落。如果每个地方都手动review代码,会耗费大量的时间。为了减少工作量,我们决定从模型入手。考虑到并非所有模型都有脱敏信息,定义一个特征来处理敏感信息似乎是一种相对安全的方式。我们脱敏的主要思路是对__get()和__set()这两个魔术方法进行改造,希望尽量减少对类似User::model()->username的使用的影响,以Yii1.1框架作为一个例如,修改find??ByAttributes()等方法,避免大量findByXXX()方法失败publicfunction__get($name){//getPlainKeys()定义模型中需要的脱敏信息字段if(in_array($name,$this->getPlainKeys())){$enc_name=Mask::getMaskName($name);//encrypt_usernameif(empty($this->$enc_name)){returnparent::($name);}//兼容代码,用户数据未更新时调用}$plain_value=Mask::encrypt(Mask::getMaskType($name),$this->$name);//返回明文return$plain_value;}else{returnparent::($name);//不使用$this->$name,防止多次调用__get()}}重写__get()方法后,定义一个getPlain()方法,传入返回明文字段,通过User::model()->getPlain(['username'])->username的方法返回需要的明文即可。在此之前,需要在需要脱敏的模型中加入预脱敏。敏感信息字段$mask_key['username','mobile']/***向数组中插入值**/publicfunctiongetPlain($keys){foreach($keysas$key){if(in_array($key),$this->getMaskName())){//比较掩码_keyarray_merge($this->getPlainKeys(),$keys);}}返回$this;}当然,如果直接通过User::model()->username的地方很多,需要明文的地方也很多,只要在model中加一个$plain_keys字段,默认返回明文即可,以及添加一个方法可以移除$plain_keys中的值,比如User::model()->removePlainKeys('username')->username返回编码后的明文。publicfunction__set($name,$value){if(in_array($name,$this->getMaskKeys())){...//生成字段名encrypt_username,plain_usernameif(empty($value)){//为了防止某些情况下敏感信息被写回空值,enccrypt_username的存在会返回旧的历史数据$this->setAttributes($name,'');$this->setAttributes($encrypt_username,'');$this->setAttributes($plain_username,'');$data=Mask::doencrypt(Mask::getMaskType($name),$value)$this->setAttributes($name,$data['plain_text']);$this->setAttributes($encrypt_username,$data['hash']);$this->setAttributes($plain_username,$价值;}else{reutrnparent::__set($name,$vk)}}