Laravel Eloquentのcast機能で暗号化した値をDBに保存する

こんにちは。

やりたいこと

EloquentのCastで暗号化

手順

Eloquentモデルとマイグレーション作成

まずはCustomerモデルとデータベースのテーブルを作りましょう。make:modelに–migrationオプションを付けてマイグレーションまで一気に作ります。

$ php artisan make:model Customer --migration

以下が作成される
app/Models/Customer.php
database/migrations/yyyy_mm_dd_hhmmss_create_customers_table.php

次にマイグレーションを編集します。属性はid、name(顧客名)、address(住所)を持つこととします。今回は個人情報を特定されないようaddress(住所)を暗号化の対象とします。

        Schema::create('customers', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('address'); // 暗号化対象
            $table->timestamps();
        });

artisan migrateコマンドでテーブルを作成します。

$ php artisan migrate

Customerモデルに暗号化のCastを設定

Customerモデルに暗号化のキャストを設定します。$cast配列内に’address’ => 'encrypted’と定義すればOKです。こうすることでORMを使ったデータベースへの保存時にaddressを暗号化して保存してくれます。反対にデータベースから取得する場合は暗号を復号化してくれます。


class Customer extends Model
{
    use HasFactory;

    protected $casts = [
        'address' => 'encrypted',
    ];
}

動作検証

tinkerを使ってCustomerモデルを保存してみましょう。

>>> use App\Models\Customer;
>>> $customer = new Customer();
=> App\Models\Customer {#3722}
>>> $customer->name = 'sample customer';
=> "sample customer"
>>> $customer->address = 'shinjuku-ku tokyo';
=> "shinjuku-ku tokyo"
>>> $customer->save();
=> true

データベースに保存されたデータを確認します。addressには暗号化された値が保存されていることがわかります。

今度は先程作成したデータをEloquentを利用して取得します。

>>> $customer = Customer::find(2); // findメソッドでモデルを取得。
=> App\Models\Customer {#4450 // 取得した時点ではaddressが暗号化されている。
     id: "2",
     name: "sample customer",
     address: "eyJpdiI6ImlyNkVCd1hKT2taQ0ZaUUJzNlVRWVE9PSIsInZhbHVlIjoiTm1qNWErODR3cU5EaGZPZlBtUGlaNXRWeFNRdWpIazZoL2p5eit0WDEvMD0iLCJtYWMiOiIyYTNhZWNhYWFkMGMxOGEyODE2OGViYWZjYThjMjAyNzNiNWEyMzU3ZjllYTE2ODZmMWNhNDAwMTQ3YzlkZGIzIiwidGFnIjoiIn0=",
     created_at: "2021-11-13 02:15:33",
     updated_at: "2021-11-13 02:15:33",
   }
>>> $customer->address; // addressをモデルから参照
=> "shinjuku-ku tokyo" // 値が復号化される

値が復号化されて取得できました。

暗号化castを利用する際の注意事項

暗号化のロジックをモデル内にカプセル化できるため、非常に便利です。しかし同時に注意したい事項もありますので2点紹介します。

暗号化した項目は検索できない

当たり前ですが暗号化した値を検索することはできません。Eloquentのwhereで検索できないという意味になります。暗号化するかどうかは要件定義や設計時の決め事ですので、よく検討する必要がありそうです。

Eloquent以外で取得する際は復号化ロジックを自分で記述する必要がある

これも当たり前ですがQueryBuilderで登録、取得する場合は暗号化ロジックは自身で記述する必要があります。特に登録時に暗号化を忘れると、平文と暗号文が入り混じりますので注意が必要です。

まとめ

今回は暗号化Castについて解説しました。適切に使うことで暗号化の処理をEloquent内にカプセル化し、処理をひとまとめにすることができます。暗号化の要件が発生した際には使わない手はないと思います。

Laravel

Posted by kobainmac