必须将数据库字段类型改为TEXT或MEDIUMTEXT(MySQL)或BLOB(SQLite),而非VARCHAR(255);模型中应使用$casts = ['field' => 'encrypted']自动加解密;严禁用encrypt()存密码,仅适用于需明文读取的敏感数据;APP_KEY须严格保密、统一且不可变更。

用 encrypt() 和 decrypt() 加密字段前必须改数据库类型
直接在模型里调用 encrypt() 存字符串,但数据库字段还是 VARCHAR(255)?存不进去或解密失败是大概率事件。Laravel 加密后生成的是 base64 字符串,带填充和 IV,长度远超原始值——比如加密一个空字符串也会产出约 144 字符。
- MySQL 推荐用
TEXT或MEDIUMTEXT,别用VARCHAR(尤其VARCHAR(255)) - SQLite 注意 blob 字段更稳妥,
TEXT也可,但避免CHAR - 迁移中写
$table->text('api_key_encrypted');,别图省事沿用旧字段类型
模型中用 casts 自动加解密比手动调用更安全
手动在 save() 前调 encrypt()、取值时再 decrypt(),容易漏掉一处就裸奔。Laravel 的 cast 机制会在属性设值/取值时自动触发,且对批量赋值(fill()、create())也生效。
- 在模型里加:
protected $casts = ['api_token' => 'encrypted']; - 这个
encryptedcast 是 Laravel 9+ 内置的,不需要额外包 - 它底层用的是
encrypt()/decrypt(),但会处理异常:解密失败时返回null,不会抛错中断请求 - 注意:只对
get/set属性有效,where()查询不能用加密字段做条件(加密后值不可索引)
encrypt() 不是哈希,别拿它存密码
有人看到“加密”就下意识用来替代 Hash::make(),这是危险操作。加密可逆,哈希不可逆——用户密码一旦被解密,整个账户体系就崩了。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
- 密码永远走
Hash::make($password)+Hash::check() -
encrypt()只适合存第三方密钥、API token、用户偏好等需要后续读取明文的敏感字段 - 密钥轮换困难:
encrypt()依赖APP_KEY,换 key 后旧数据全部无法解密,没迁移方案
生产环境启用加密前必须确认 APP_KEY 稳定且未泄露
APP_KEY 是整个加密体系的命门。它不仅用于 session、CSRF,也直接参与 encrypt() 的 AES 密钥派生。一旦泄漏,所有加密字段可被批量解密;一旦误改,存量数据永久失效。
- 检查
.env中APP_KEY是否为php artisan key:generate生成的 32 字符随机串 - 禁止把
APP_KEY提交到 Git —— 确保.env在.gitignore里 - 多服务器部署时,所有实例必须用同一
APP_KEY,否则 A 机器存的,B 机器读不出来
加密不是开关一开就完事,字段类型、cast 机制、密钥生命周期、使用边界,四个点缺一不可。少盯住一个,上线后就是静默故障。

















