webqamdev/encryptable-fields

Laravel Backpack Fields Encryptable

3.0.0 2024-08-14 08:31 UTC

README

Latest Version on Packagist Total Downloads

允许您加密模型字段。您可以为SQL查询添加一个散列字段。

安装

您可以通过composer安装此包

composer require webqamdev/encryptable-fields

您可以通过Artisan发布配置

php artisan vendor:publish --provider="Webqamdev\EncryptableFields\EncryptableFieldsServiceProvider"

使用方法

要使用此包,您需要在模型中使用我们的EncryptableFields特性,然后重写$encryptable属性。此数组允许您在模型中定义可加密属性。

您还可以添加包含非加密值散列的属性,这可能有助于对给定搜索值执行快速全匹配。

为此,您需要将$encryptable属性用作关联数组,其中可加密属性是键,关联散列属性是值。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Webqamdev\EncryptableFields\Models\Traits\EncryptableFields;

class User extends Model
{
    use EncryptableFields;

    const COLUMN_LASTNAME = 'lastname';
    const COLUMN_LASTNAME_HASH = 'lastname_hash';
    const COLUMN_FIRSTNAME = 'firstname';
    const COLUMN_FIRSTNAME_HASH = 'firstname_hash';
    const COLUMN_EMAIL = 'mail';

    /**
     * The attributes that should be encrypted in database.
     * 
     * @var string[] 
     */
    protected $encryptable = [
        self::COLUMN_FIRSTNAME => self::COLUMN_FIRSTNAME_HASH,
        self::COLUMN_LASTNAME => self::COLUMN_LASTNAME_HASH,
        self::COLUMN_EMAIL,
    ];

要创建新模型,只需像以前一样做即可

User::create(
    [
        User::COLUMN_FIRSTNAME => 'watson',
        User::COLUMN_LASTNAME => 'jack',
    ]
);

从散列值中查找模型

User::where(User::COLUMN_FIRSTNAME_HASH, User::hashValue('watson'))->first();

或使用模型的本地作用域

User::whereEncrypted(User::COLUMN_FIRSTNAME, 'watson')->first();

身份验证

此包注册了一个名为eloquent-hashed的认证提供者,允许在散列属性上对用户进行身份验证,例如电子邮件。要使用它,只需更改您的认证配置如下

return [
    // ...
    
    'providers' => [
        'users' => [
            'driver' => 'eloquent-hashed',
            'model' => App\Models\User::class,
        ],
    ],
    
    // ...
];

可搜索的加密值

MySQLMariaDB 都提供了aes_decrypt函数,允许在查询时直接解密值。然后可以使用此函数来过滤或排序加密值。

然而,Laravel默认加密器仅处理AES-128-CBCAES-256-CBC加密方法,而MySQL和MariaDB需要AES-128-ECB。我们将使用两个不同的密钥。

为此,将以下变量添加到您的.env文件中

APP_DB_ENCRYPTION_KEY=

并运行php artisan encryptable-fields:key-generate命令以生成数据库加密密钥。

⚠️ 您不应该自己生成此密钥,因为Laravel与MySQL/MariaDB之间的加密方式不同。

然后,需要重写Laravel的默认加密器,这已在DatabaseEncrypter.php中完成。

在您的config/app.php中包含DatabaseEncryptionServiceProvider,以便在项目中的databaseEncrypter键下注册单例实例

return [
    // ...

    'providers' => [
        // ...

        /*
         * Package Service Providers...
         */
        Webqamdev\EncryptableFields\Providers\DatabaseEncryptionServiceProvider::class,

        // ...
    ],
    
    // ...
];

最后,在encryptable-fields.php文件中重写包配置

return [
    // ...

    // Need to implement EncryptionInterface
    'encryption' => Webqamdev\EncryptableFields\Services\DatabaseEncryption::class,

    // ...
];

⚠️ 在DatabaseEncrypter.php中,为了允许使用精确值查询(使用=而不是like运算符),值不会被序列化,这意味着它不会处理对象实例或数组。

如果您在项目中使用Laravel Backpack,一个名为EncryptedSearchTrait的特质提供了自定义搜索和排序逻辑的方法。

use Illuminate\Database\Eloquent\Builder;

CRUD::addColumn([
    // ...
    
    'searchLogic' => function (Builder $query, array $column, string $searchTerm): void {
        $this->encryptedSearchLogic($query, $column['name'], $searchTerm);
    },
    'orderLogic' => function (Builder $query, array $column, string $columnDirection): void {
        $this->encryptedOrderLogic($query, $column['name'], $columnDirection);
    },
    
    // ...
]);

验证

此包包含一些规则来验证散列或加密属性的存续性和唯一性。

它们作为Illuminate\Validation\Rules\ExistsIlluminate\Validation\Rules\Unique的扩展。

散列

use Webqamdev\EncryptableFields\Rules\Exists\Hashed;

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules(): array
{
    return [
        'email' => [
            new Hashed(User::class, 'email'),
            // or new Hashed('users', 'email'),
        ],
    ];
}

use Webqamdev\EncryptableFields\Rules\Unique\Hashed;

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules(): array
{
    return [
        'email' => [
            new Hashed(User::class, 'email'),
            // or new Hashed('users', 'email'),
        ],
    ];
}

加密

use Webqamdev\EncryptableFields\Rules\Exists\Encrypted;

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules(): array
{
    return [
        'email' => [
            new Encrypted(User::class, 'email'),
            // or new Encrypted('users', 'email'),
        ],
    ];
}

use Webqamdev\EncryptableFields\Rules\Unique\Encrypted;

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules(): array
{
    return [
        'email' => [
            new Encrypted(User::class, 'email'),
            // or new Encrypted('users', 'email'),
        ],
    ];
}

在日志中隐藏解密值

如果您的应用程序使用 spatie/laravel-activitylogwebqamdev/activity-logger-for-laravel
在每个带有日志的模型中添加 HasEncryptableFieldsLog 特性。
该特性在日志中打印加密的值,而不是解密值。

测试

composer test

更新日志

有关最近更改的更多信息,请参阅 更新日志

贡献

有关详细信息,请参阅 贡献指南

鸣谢

许可

MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件

Laravel 包模板

此包使用 Laravel 包模板 生成。