Laravel Eloquent – Encrypt/Decrypt Data on call

在開發商業網站的時候,對資料加密是必要的手段,尤其是資料庫中關於會員隱私,或是商業機密的部份都要特別處理。

在實務上通常不會用資料庫內建的加密功能,而是用後端語言來實現 encrypt 與 decrypt,資料庫只儲存加密後的訊息。

在 Laravel 裡加解密可以透過繼承 Eloquent,用 magic function 來達成自動化。

class BaseModel extends Eloquent {

    protected $encrypt = [];

    public function setAttribute($key, $value)
    {
        if (in_array($key, $this->encrypt))
        {
            $value = Crypt::encrypt($value);
        }

        return parent::setAttribute($key, $value);
    }

    public function getAttribute($key)
    {
        if (in_array($key, $this->encrypt))
        {
            return Crypt::decrypt($this->attributes[$key]);
        }

        return parent::getAttribute($key);
    }

    public function attributesToArray()
    {
        $attributes = parent::attributesToArray();

        foreach ($attributes as $key => $value)
        {
            if (in_array($key, $this->encrypt))
            {
                $attributes[$key] = Crypt::decrypt($value);
            }
        }

        return $attributes;
    }

而需要用到加解密的 Model 改繼承 BaseModel,並將需要加密的欄位寫在 $encrypt 陣列中即可。

需要搜尋加密欄位的時候,可以參考以下作法…

$match = User::all()->filter(function($record) use($email) {
            $field = $record->email['email'];

            if(Crypt::decrypt($field) == $email) return $record;
         });

這個作法會 scan table,效率應該會很糟。但 Laravel 預設的加密方式會自動加鹽,相同的明文配相同的金鑰也會產出不一樣的密文,暫時只想到這種解決。

for($i = 1; $i <= 10; $i++)
{
    // 會得到十種結果
    echo "\n". Crypt::encrypt('secret');
}

先醬,想到再補充。


Posted

in

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *