---
title: 给文件上传加几道锁：类型、大小、路径、执行权限
site: 星湖の小窝
category: 后端
tags: [后端, 上传, 安全]
date: 2026-10-04
updated: 2026-10-04
id: note-upload-hardening
---

# 给文件上传加几道锁：类型、大小、路径、执行权限

文件上传的危险在于：一旦能传可执行文件、又能访问它，就等于给了对方一个入口。下面几道锁缺一不可。

### 第一道：按内容判类型，不看扩展名

浏览器传来的类型和文件名都能伪造，用 `getimagesize()` 这类函数读文件头判断：

```php
$info  = @getimagesize($tmp_path);
$allow = array(IMAGETYPE_JPEG => 'jpg', IMAGETYPE_PNG => 'png', IMAGETYPE_GIF => 'gif');

if (!$info || !isset($allow[$info[2]])) {
    exit('只支持 jpg / png / gif');
}
```

> 特别注意 SVG：它是 XML，可以内嵌脚本，等于 XSS。个人站点一般直接不收。

### 第二道：文件名由服务端生成

原文件名里可能带 `../`、空格、特殊字符。统一改成「日期 + 随机串 + 后缀」，原文件名只用来生成标题。

### 第三道：限制体积

- PHP 的 `upload_max_filesize` 与 `post_max_size` 要一起看 —— 超过 post_max_size 时整个请求会被丢掉
- 代码里再判一次，并给用户看得懂的提示（"原图 6.2MB，超过上限 2MB"）

### 第四道：上传目录不许执行

这是最重要的一道。在 `uploads/` 里放一个 `.htaccess`：

```apache
php_flag engine off
AddType text/plain .php .phtml .php5 .php7 .pht
Options -ExecCGI
```

Nginx 环境则在站点配置里对该目录加 location 限制。注意部分主机（例如 Kangle）不读 .htaccess，那就更要靠「类型白名单 + 服务端命名」这两道。

### 第五道：别把真实路径回给前端

错误信息里不要出现服务器绝对路径；图片用相对路径或专门的输出接口。

### 顺手加一条：限流

上传接口按小时限制次数，避免被当成免费图床。
