You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel查询的WHERE子句中使用Crypt解密实现搜索?

解决方案

要实现加密登录信息的搜索,核心是在数据库查询阶段完成解密并匹配关键词,因为through()是在查询结果返回后处理,无法作用于WHERE子句。以下是基于MySQL数据库的实现方案:

1. 核心思路

Laravel的Crypt::encrypt()生成的密文是包含iv、加密内容的JSON字符串的Base64编码,因此可以通过数据库的JSON解析和AES解密函数,在WHERE子句中直接解密password_login字段并匹配搜索关键词。

2. 修改后的查询代码

// 解析APP_KEY,去掉base64:前缀后解码为原始密钥
$appKey = base64_decode(substr(config('app.key'), 7));

$passwords = Password::query()
    ->when($filter_category, function($q) use ($filter_category){
        $q->where('category_id', $filter_category);
    })
    ->when($filter_search, function($q) use ($filter_search, $appKey){
        $q->whereHas('category', function ($q) use ($filter_search){
            $q->where('category_name', 'LIKE', "%$filter_search%");
        })
        // 保留原有的密码名称搜索
        ->orWhere('password_name', 'LIKE', "%$filter_search%")
        // 添加登录信息解密搜索
        ->orWhereRaw(
            "AES_DECRYPT(FROM_BASE64(JSON_UNQUOTE(JSON_EXTRACT(FROM_BASE64(password_login), '$.value'))), ?, FROM_BASE64(JSON_UNQUOTE(JSON_EXTRACT(FROM_BASE64(password_login), '$.iv')))) LIKE ?",
            [$appKey, "%$filter_search%"]
        );
    })
    ->where('user_id', Auth::id())
    ->paginate(10)
    ->through(function ($password) {
        if ($password->password_login) {
            $password->password_login = $this->formatLogin(Crypt::decrypt($password->password_login));
        }
        return $password;
    });

3. 关键说明

  • 数据库版本要求:需要MySQL 5.7.4+或MariaDB 10.2+,确保支持JSON解析函数和带IV参数的AES_DECRYPT(CBC模式)。
  • 性能问题:该方案需要对每一行数据进行解密操作,无法利用索引,数据量大时查询速度会变慢。如果数据量较大,建议:
    • 使用确定性加密存储一个可搜索的额外字段(如searchable_login),但需注意相同明文会生成相同密文的安全风险;
    • 改用支持字段级加密的数据库特性(如MySQL透明数据加密)。
  • 密钥安全:直接使用Laravel的APP_KEY即可,不要硬编码密钥,确保APP_KEY的保密性。

内容的提问来源于stack exchange,提问作者LordzSpectron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 04:35:33