laravel原生不支持eloquent字段透明加解密,需借助laravel-encryptable等扩展包;该包通过booting钩子劫持属性访问与查询构建,实现自动加解密及where条件转译,但加密字段不可索引、不支持like等数据库操作。

Laravel 本身不提供 Eloquent 模型字段的透明加解密,必须手动集成或借助扩展包;原生 Eloquent 不会自动加密/解密数据库值,哪怕你用了 casts 或访问器/修改器。
为什么不能只靠 $casts 或 getFooAttribute
因为 $casts 只处理类型转换(如 string ↔ array),不涉及加密逻辑;而访问器/修改器在模型生命周期中是“可见层”操作,where 查询、orderBy、关联预加载等场景下,数据库里存的仍是明文——除非你全程绕过 Eloquent 的查询构造器,否则根本起不到保护作用。
- 明文仍存在于 SQL 日志、慢查询日志、备份文件、DBA 权限可查的表中
-
where('email', 'like', '%@gmail%')这类查询在加密后完全失效 - 使用
encrypt/decrypt手动包裹每个赋值点,极易漏写、难维护
推荐方案:用 laravel-encryptable 包实现字段级透明加解密
它通过 Eloquent 的 booting 钩子劫持 setAttributes 和 getAttribute,并在 toBase(构建查询前)重写 where 条件为加密后的值,真正实现“写入自动加密、读取自动解密、查询自动转译”。
- 安装:
composer require w3bstream/laravel-encryptable - 在模型中 use
Encryptabletrait,并声明$encryptable = ['ssn', 'phone'] - 确保字段是
TEXT类型(加密后是 base64 字符串,长度远超原始值) - 不支持
LIKE、JSON_CONTAINS等模糊/结构化查询——加密后数据不可索引、不可比较
自定义加密字段时,APP_KEY 和 APP_CIPHER 必须稳定
一旦上线,APP_KEY 绝对不能重置,否则所有已加密字段永久无法解密。Laravel 默认用 OpenSSL + AES-256-CBC,但如果你改过 APP_CIPHER(比如换成 AES-128-GCM),老数据就再也读不出来了。
- 加密密钥由
APP_KEY衍生,不是直接使用——别试图用它加密其他系统数据 - 不要在测试环境用不同
APP_KEY,否则 seed 数据在本地能解、线上解不开 -
php artisan key:generate是危险操作,上线后禁止执行
真正麻烦的不是加解密逻辑本身,而是加密后字段彻底丧失数据库原生能力:没法建索引、没法做范围查询、没法被 MySQL 函数处理。如果业务需要按加密字段搜索,只能退回到应用层解密后 in-memory 过滤,或者另建脱敏哈希字段辅助查询。











