加密与中间状态

2024 年 4 月 4 日#教程

去年,我们为 Laravel Forge 引入了一个简单但出人意料地有用的功能:向服务器添加备注的能力。

在检查此功能的采用情况时,我们注意到客户经常在该字段中存储敏感数据。我们并未设计备注来存储敏感信息,因此我们发现自己现在需要对现有的未加密数据进行加密,同时还要允许将新数据作为加密数据插入 - 同时,无论备注是否已加密,仪表板都需要能够正确显示备注。

我们的迁移过程如下

  1. 运行一个命令,对所有现有的未加密服务器备注进行加密。
  2. 更新我们的模型以转换 notes 字段,根据需要进行加密或解密。

为此,我们依靠 Laravel 的自定义转换 功能来处理此“有时加密”的数据。我们创建了一个新的转换 SometimesEncrypted,它允许我们优雅地解密加密的备注,或简单地返回在迁移期间可能可用的明文版本

<?php

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Crypt;

class SometimesEncrypted implements CastsAttributes
{
    /**
     * Cast the given value.
     *
     * @param  array<string, mixed>  $attributes
     */
    public function get(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        if ($value === null || $value === '') {
            return $value;
        }

        try {
            return Crypt::decryptString($value);
        } catch (DecryptException $e) {
            return $value;
        }
    }

    /**
     * Prepare the given value for storage.
     *
     * @param  array<string, mixed>  $attributes
     */
    public function set(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        return ($value === null || $value === '') ? null : Crypt::encryptString($value);
    }
}

使用此转换意味着我们还可以分两部分发布此更改

  1. 转换备注字段,在保存新服务器备注时对其进行加密。
  2. 通过将明文服务器备注存储回模型并允许 SometimesEncrypted 转换发挥作用,来迁移明文服务器备注。

Laravel 的自定义转换允许我们为用户实现无缝过渡,在不中断用户体验或现有功能的情况下加密敏感数据。你发现使用 Laravel 的自定义转换的哪些有趣方法?

作者:詹姆斯·布鲁克斯

Laravel 工程团队负责人,构建 ForgeVaporEnvoyer

TwitterGitHub我的博客 上找到我。

关注 RSS Feed