敏感字段必须在API Resource中显式脱敏,禁用模型层$hidden/$casts保护;禁用dd/dump;日志白名单过滤;$casts不参与脱敏;导出/推送/队列等非API场景需单独处理。

敏感字段在 API 响应里直接暴露 password、id_card、phone
这是最常见也最危险的泄露点:模型直接转 JSON 返回,没做任何过滤。Laravel 的 toArray() 和 API Resource 默认都会把所有属性吐出来,包括你加了 $hidden 但忘了在 Resource 里同步处理的字段。
实操建议:
- 永远不要依赖模型层的
$hidden或$casts来保护 API 输出——API Resource 才是最终出口,必须显式控制 - 用
JsonResource逐字段定义,而不是继承ResourceCollection后靠toArray()模糊兜底 - 手机号脱敏统一用
substr($phone, 0, 3) . '****' . substr($phone, -4),别写正则替换再 trim,容易漏空格或带区号格式
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'phone' => $this->when($this->relationLoaded('profile'), function () {
return substr($this->profile->phone, 0, 3) . '****' . substr($this->profile->phone, -4);
}),
'email' => $this->when($request->user()?->can('view_email'), $this->email),
];
}
}
dump()、dd() 在生产环境没关掉
开发时随手打的 dd($user) 如果混进上线代码,会把整个模型连同关联数据、原始 SQL 绑定参数全打出来——password_hash、remember_token 全在其中。
实操建议:
- 上线前全局搜索
dd(、dump(、die(,一个都不能留 - 用 Laravel Pint + 自定义规则,在 CI 阶段自动拦截含调试函数的提交
- 配置
APP_DEBUG=false后,dd()仍会执行,只是不显示堆栈——它照样把数据吐到响应体里,这点很多人误以为“关了 DEBUG 就安全了”
日志里记录了 Request::all() 或完整异常上下文
比如在 App\Exceptions\Handler 里用 Log::error('Request failed', ['data' => $request->all()]),或者没过滤就记录 $exception->getTraceAsString(),都可能把密码、token 写进日志文件。
实操建议:
- 禁用
$request->all(),改用白名单:$request->only(['name', 'email']) - 自定义日志上下文时,对敏感键名硬过滤:
Arr::except($data, ['password', 'token', 'api_key']) - 数据库查询日志开启前确认
DB::enableQueryLog()只在本地启用,且config/database.php中'log_queries' => env('DB_LOG_QUERIES', false)明确关闭生产环境日志
Eloquent 模型的 $casts 和访问器混用导致脱敏失效
有人在模型里写 $casts = ['phone' => 'string'],又加了个 getPhoneAttribute() 访问器做脱敏,结果发现 API 里还是明文——因为 $casts 优先级高于访问器,字符串 cast 后直接返回原始值,访问器根本没触发。
实操建议:
- 脱敏逻辑只放在 Resource 或访问器里,模型层
$casts仅用于类型转换(如'is_active' => 'boolean'),不参与数据变形 - 如果必须用访问器,确保字段不在
$casts列表中,否则 cast 会劫持取值流程 - 测试时用
php artisan tinker直接调User::first()->phone看结果,比跑一遍 API 更快暴露问题
真正难防的不是技术点,是那些“我以为已经处理了”的地方:比如导出 Excel 时忘了脱敏、WebSocket 推送用户信息时绕过了 Resource、队列任务里直接序列化了模型对象。这些环节往往没有统一出口,得一个个抠。









