必须对敏感文件路径进行不可逆加密混淆:上传时用crypt::encryptstring()加密文件名+用户id+时间戳生成密文路径,存入数据库encrypted_path字段(text类型);下载时通过路由接收密文,解密后流式响应,严禁暴露原始路径。

在 Laravel 项目中,当用户上传身份证、合同、医疗报告等敏感文件时,原始文件名和存储路径若直接暴露(如 storage/app/users/123/ID_张三_20250401.jpg),极易被枚举或猜解,导致隐私泄露;必须对路径结构和文件标识进行不可逆混淆,而非简单重命名。
生成加密文件路径并写入磁盘
第一步:在上传逻辑中,用 Crypt::encryptString() 对原始文件名 + 用户 ID + 时间戳拼接后的字符串加密,得到唯一密文路径片段。
第二步:将密文作为子目录名和文件名主体,拼接为完整路径:storage/app/enc/{encrypted_dir}/{encrypted_name}.jpg。
第三步:调用 Storage::put($full_path, $file_content) 写入——【这一步必须在 APP_KEY 未被重置的前提下执行,否则后续所有解密均失败】。
从加密路径安全读取并响应文件
方法一:通过路由参数接收密文路径(如 /download/abc123def456),在控制器中先尝试 Crypt::decryptString() 解密;失败则立即返回 404,不记录日志、不抛出异常堆栈。
方法二:解密成功后,用 Storage::get($decrypted_path) 读取原始内容,再用 response()->streamDownload() 输出,避免内存加载大文件。
注意:不要把解密后的原始路径拼成 public URL 暴露给前端——这会绕过所有保护,让加密形同虚设。
数据库中只存密文路径,不存任何可推导信息
① 创建 migration,为文件表添加 encrypted_path 字段,类型必须为 TEXT(VARCHAR(255) 会截断 base64 密文)。
② 上传成功后,仅将 enc/{encrypted_dir}/{encrypted_name}.jpg 存入该字段,绝不写入原始文件名、用户 ID 或时间戳。
③ 查询时禁止使用 LIKE、% 匹配 encrypted_path 字段——它本质是随机字符串,模糊查询无意义且易触发全表扫描。
④ 删除文件前,先查出 encrypted_path,调用 Storage::delete($path),再删除数据库记录;顺序不可颠倒。











