记录一次敏感信息脱敏的过程

背景:

在A公司入职,老大让我去做数据脱敏,通过调用运维组的数据脱敏接口,保证用户的敏感的信息不落地。公司项目主要使用laravel5.1 和 YII1.1 版本。

具体方案:

敏感信息字段的调用存在与代码中的各个角落,如果手动对每一个地方的代码都去撸一边,所需要耗费的时间是非常巨大的,为了减少工作量,我们决定对model下手,考虑到并不是所有的model都存在脱敏信息,单独定义一个trait来处理存在敏感信息似乎是一个相对比较稳妥的方式。

我们对于脱敏的主要思想是对__get()和__set()两个魔术方法的改造,希望在最大程度的减少对使用类似User::model()->username的影响,以Yii1.1框架为例,还要改造findByAttributes()等方法避免大量findByXXX()方法的失效

public function __get($name)
{
    //getPlainKeys() 定义了model当中的需要的脱敏信息字段
    if(in_array($name, $this->getPlainKeys())) {
        $enc_name = Mask::getMaskName($name);//encrypt_username
        if(empty($this->$enc_name)) {
            return parent::($name); //兼容代码,用户数据未更新时调用
        }
        $plain_value = Mask::encrypt(Mask::getMaskType($name), $this->$name);//返回明文
        return $plain_value;
    }else {
        return parent::($name);//不要使用$this->$name 防止多次调用__get()
    }
}

重写完__get()的方法后,在定义一个getPlain()的方法,传入返回明文的字段,
通过User::model()->getPlain(['username'])->username的方法返回需要的明文就好了,在这之前,需要在需要脱敏的model里面加好订好的脱敏信息的字段$mask_key['username','mobile']

   /**
    * 往数组里塞值
    **/
    public function getPlain($keys)
    {
        foreach($keys as $key){
            if(in_array($key, $this->getMaskName())) {//比较mask_key
                array_merge($this->getPlainKeys(), $keys);         }
        }
        return $this;  
    }

当然了,如果直接通过User::model()->username的地方很多,又需要明文的地方很多,就在model里面直接添加一个$plain_keys的字段去默认返回明文就好了,同时去新增一个能够将$plain_keys里面的值移除的方法就好了,例如User::model()->removePlainKeys('username')->username返回打码明文就好了.

public function __set($name, $value)
{
    if(in_array($name, $this->getMaskKeys())){
        ... //产生字段名称encrypt_username, plain_username
        if(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, $value;
    }else {
        reutrn parent::__set($name, $vk)
    }
}

你可能感兴趣的:(记录一次敏感信息脱敏的过程)