标准Flask项目模板(一键脚本)
flask secure_filename 安全命名
secure_filename() 在很多情况下非常有必要,尤其是在处理用户上传文件时。
💡 背景
当你让用户上传文件(比如 Flask 中的 request.files['file']),
用户的文件名可能包含各种危险或特殊内容,比如:
../../../etc/passwd
my file.png
script<script>.jpg
这些名字在操作系统、服务器、或 URL 中使用时可能导致问题,比如:
- 路径穿越攻击(Path Traversal)
- 特殊字符错误
- 不同系统编码不兼容
- 无法正确保存或访问文件
✅ Flask 的解决方法
Flask 提供了 werkzeug.utils.secure_filename 来自动清理文件名:
from werkzeug.utils import secure_filename
filename = secure_filename(uploaded_file.filename)
uploaded_file.save(f"./uploads/{filename}")
secure_filename("../../../etc/passwd") 👉 会变成
etc_passwd
secure_filename("my file.png") 👉 会变成
my_file.png
⚠️ 如果不用 secure_filename 会怎样?
假设你写:
f.save("./uploads/" + f.filename)
而用户上传的文件名是:
../../app.py
那你可能覆盖掉你自己的代码文件,甚至被攻击者写入恶意脚本。😱
💬 总结
| 场景 | 是否建议用 secure_filename |
|---|---|
| 用户上传文件 | ✅ 必须用 |
| 你自己在代码里创建的文件 | ❌ 不需要 |
| 文件名来自外部 API 或第三方输入 | ✅ 建议用 |
改进 secure_filename,让中文保留
Werkzeug 的 secure_filename 默认只保留 ASCII 字母。 你可以写一个小函数,保留中文和常见字符:
import re
def safe_filename(filename):
# 保留中文、英文、数字、下划线、点、横线
return re.sub(r'[^0-9A-Za-z\u4e00-\u9fa5._-]', '_', filename)
然后替换原来的:
song_filename = safe_filename(song.filename)
这样:
“夏天的风(完整版).flac” → “夏天的风_完整版_.flac”
“My Song.mp3” → “My_Song.mp3”
会安全又美观 ✅