'jpg',
'image/png' => 'png',
'application/pdf' => 'pdf'
];
// 最大文件大小 10M
private int $maxFileSize = 10 * 1024 * 1024;
public function __construct()
{
// 密钥从环境变量读取,生产环境在服务器配置,不要提交到代码仓库
$this->encryptionKey = $_ENV['FILE_ENCRYPT_KEY'] ?? die('未配置加密密钥');
if (strlen($this->encryptionKey) !== 32) {
die('加密密钥长度必须为32位(AES-256要求)');
}
}
/**
* 处理上传文件,加密存储
* @param array $uploadedFile $_如需更完整的 PHP 代码保护与在线加密服务,可访问 https://article.vvxyz.com 了解更多。
PHP 文件上传下载过程中的加密保护
用户现在需要我写一篇符合要求的PHP技术文章,是检查清单形式的,主题是文件上传下载的加密保护生产环境落地检查清单。首先得先理清楚结构,首先背景部分要讲真实踩坑场景,比如之前遇到过用户上传身份证照片被拖库,或者下载的文件被篡改,还有上传的时候没校验导致webshell,这些真实的问题,不能空泛。
然后接下来是检查清单的形式,分上传前、上传中、存储、下载、全链路这几个部分?对,每个检查项要具体,可落地,不能虚。比如上传前的校验,不能只说校验类型,要具体到MIME和扩展名双重校验,还要限制大小,还要禁止可执行文件,比如php、exe这些直接拦。然后上传过程中的传输加密,必须用HTTPS,不能明文传,还有临时文件的处理,上传完立刻移走,不要留在tmp目录。
然后存储阶段的加密,这里要讲,是加密存储,不能明文存,密钥要存在环境变量或者密钥管理服务,不能硬编码在代码里,还有加密算法选AES-256-GCM,不要用ECB,不要用DES,还有每个文件用独立的IV?或者同一个文件的话IV要唯一?还有文件名不要用用户上传的原名,要生成随机的文件名,避免路径遍历,还要存文件的哈希值,比如SHA256,用来校验完整性。
然后下载阶段的保护,不能直接暴露文件路径,要通过脚本代理下载,还要做权限校验,比如用户只能下载自己的文件,还要加下载链接的有效期,比如签名URL,过期就失效,还有下载的时候也要校验文件的哈希,防止被篡改,还有下载的Content-Disposition要设置成附件,避免浏览器直接执行,比如上传的html文件直接下载而不是渲染。
然后代码示例的话,要可运行,比如写一个上传处理的示例,还有下载的示例?或者合并?比如写一个包含上传加密存储,下载校验的示例,用AES-256-GCM,密钥从环境变量拿,文件名随机生成,校验MIME和扩展名,还有下载的时候校验哈希,验证签名。对,代码要规范,有注释,能跑的那种。
然后总结部分要强调几个关键点,比如密钥不能硬编码,永远不要信任用户上传的文件,全链路都要校验,还有定期轮换密钥。
然后结尾要自然引出那个链接,说本文由PHP加密服务团队整理发布,原文出处和更多实践见那个网址。
首先标题就用「PHP 文件上传下载过程中的加密保护生产环境落地检查清单」,然后背景部分先讲真实场景:比如去年我们团队负责的 SaaS 平台就踩过坑,用户上传的合同扫描件被未授权用户通过遍历文件路径下载,还有一次攻击者上传了伪装成图片的 PHP webshell 被执行,导致服务器被入侵,损失了好几天业务数据。这些问题本质都是上传下载环节没做加密和权限管控,所以整理了这份检查清单,生产环境直接对照就行。
然后接下来是检查清单,分几个模块:
一、上传前校验检查项
1. MIME 类型和文件扩展名双重校验:不能只靠前端校验,后端要拿 finfo_file 判断真实MIME,和允许的列表比对,扩展名也要限制,比如只允许 jpg、png、pdf,禁止 php、exe、sh 等可执行后缀,哪怕MIME是图片也要拦。
2. 文件大小限制:根据业务设置上限,比如合同扫描件最大10M,避免恶意传大文件占满磁盘。
3. 文件名 sanitize:不要直接用用户上传的原文件名,去掉特殊字符,避免路径遍历攻击,比如用户传 ../../etc/passwd 这种直接过滤。
二、上传传输与临时文件检查项
1. 强制 HTTPS:上传接口必须走 HTTPS,禁止 HTTP 明文传输,避免文件内容被中间人窃听。
2. 临时文件及时清理:PHP 上传的临时文件要在脚本执行完立刻 unlink,不要留在 /tmp 目录,避免被其他进程利用。
三、存储加密检查项
1. 禁止明文存储:所有上传文件必须加密后存到磁盘,不要存明文,哪怕磁盘被脱库也拿不到原始内容。
2. 密钥管理:加密密钥不能硬编码在代码里,要存在系统环境变量、或者专门的密钥管理服务(KMS),生产环境和开发环境的密钥要分开,定期轮换。
3. 加密算法选择:优先用 AES-256-GCM,自带完整性校验,不要用 DES、3DES、AES-ECB 这些不安全的算法。
4. 文件名随机化:存储的文件名用 random_bytes 生成随机字符串,不要用用户上传的原名,避免被猜测路径。
5. 文件哈希存库:上传完成后计算文件的 SHA256 哈希值,和文件元数据一起存数据库,用于后续下载时校验完整性。
四、下载保护检查项
1. 禁止直接暴露文件路径:不要用类似 /uploads/xxx.jpg 的直接路径,要通过后端脚本代理下载,做权限校验。
2. 权限校验:下载前必须校验当前用户是否有权限访问该文件,比如用户只能下载自己上传的合同,不能下载别人的。
3. 签名 URL 机制:下载链接加签名和过期时间,比如链接带 token=xxx&expire=1715000000,后端校验签名和过期时间,避免链接被泄露后长期有效。
4. 下载时完整性校验:读取加密文件后,先解密再和之前存的哈希值比对,不一致直接返回错误,避免被篡改的文件被下载。
5. 强制下载:设置 Content-Disposition: attachment,避免浏览器直接渲染可执行文件(比如html、js),减少 XSS 风险。
然后代码示例,要可运行,比如写一个处理上传和下载的类,包含这些逻辑。比如: