网络编程安全基础
约 1321 字大约 4 分钟
2026-05-10
网络程序经常接触外部输入、第三方服务、Token、Cookie 和文件下载,因此必须重视安全。
- 不要硬编码密钥
- HTTPS 证书校验
- SSRF 简介
- 日志脱敏
- 1Token/密钥永远从 os.environ 读取;用 .env + python-dotenv,并把 .env 加进 .gitignore。
- 2永远不要 verify=False 关闭 HTTPS 证书校验 —— 等同于把 TLS 当摆设,中间人可任意篡改。
- 3服务端请求“用户提供的 URL”要做白名单:禁 127.0.0.1/10./172.16./192.168./169.254. 等内网段,防 SSRF。
- 4保存用户提供的文件名永远用 pathlib.Path(name).name,禁止路径穿越(../../etc/passwd)。
- 5永远不要 os.system(f'curl {url}'):用户输入里塞分号就是命令注入;用 requests/subprocess + list 参数。
网络程序经常接触外部输入、第三方服务、Token、Cookie 和文件下载,因此必须重视安全。
不要硬编码密钥
不要把密码、Token、Cookie 写进代码:
TOKEN = 'secret' # 不推荐应使用环境变量:
import os
TOKEN = os.environ['API_TOKEN']HTTPS 证书校验
requests 默认会校验证书。不要随意关闭:
requests.get(url, verify=False) # 危险关闭证书校验可能导致中间人攻击。
SSRF 简介
SSRF 指服务端根据用户提供的 URL 发起请求,攻击者可能借此访问内网服务。
危险示例:
def fetch(url):
return requests.get(url).text如果 url 来自用户输入,就可能请求:
http://127.0.0.1:8000/admin
http://169.254.169.254/防护方式:
- URL 白名单
- 禁止访问内网 IP
- 限制协议只能是 http/https
- 设置超时和响应大小限制
日志脱敏
不要在日志中打印:
- Authorization Header
- Cookie
- 密码
- Token
- 身份证、手机号等敏感信息
防止命令注入
不要把 URL 或参数拼进 shell 命令:
os.system(f'curl {url}') # 危险优先使用 requests/httpx 等库,而不是调用 shell。
文件下载安全
下载文件时注意:
- 限制文件大小
- 校验 Content-Type
- 不信任服务端文件名
- 避免路径穿越
- 必要时校验哈希
代理风险
代理可以看到你的 HTTP 明文流量,也可能篡改响应。使用代理时要确认可信来源,并尽量使用 HTTPS。
依赖安全
定期更新网络相关依赖,避免已知漏洞。安装第三方库前确认来源可信。
安全不是最后才考虑
网络代码经常要处理 URL、Token、Cookie、文件、用户输入和外部响应。它们都有一个共同点:不能完全相信。
初学阶段不需要背很多安全术语,但要先养成几个习惯:
- 密钥不要写进代码;
- 不随便请求用户给的内网地址;
- 不把完整 Token 打进日志;
- 下载文件时检查大小、类型和保存路径;
- 调用系统命令时不要直接拼接用户输入。
这些习惯越早建立,后面越少踩坑。
用环境变量保存 Token
不要这样写:
TOKEN = 'sk-xxxxxxxxxxxxxxxx'更推荐:
import os
TOKEN = os.environ['API_TOKEN']
headers = {
'Authorization': f'Bearer {TOKEN}',
}运行前在终端设置:
export API_TOKEN='your-token'
python app.py这样代码提交到 Git 仓库时,不会把真实密钥一起提交上去。
日志脱敏的小函数
调试时需要打印信息,但不要把敏感值完整打印出来。可以简单处理:
def mask_secret(value, keep=4):
if not value:
return ''
if len(value) <= keep:
return '*' * len(value)
return value[:keep] + '***'
print(mask_secret('abcdef123456')) # abcd***日志里可以保留前几位帮助定位问题,但不要保留完整 Token、Cookie、密码。
小心用户传入的 URL
如果你的程序允许用户输入 URL,然后服务器去请求这个 URL,就要小心 SSRF 风险。简单说,就是用户可能让你的服务器去访问本不该访问的内部地址。
危险示例:
url = input('请输入图片 URL:')
response = requests.get(url, timeout=5)如果这是运行在服务器上的代码,用户可能输入:
http://127.0.0.1:8000/admin
http://169.254.169.254/初学阶段可以先记住:不要在服务端无条件请求用户提供的任意 URL。至少要做协议、域名、IP 范围、文件大小等限制。
下载文件时别只看文件名
用户给的文件名可能包含路径:
../../somewhere/evil.py保存文件时,不要直接拼:
# 不推荐
path = './downloads/' + filename更稳妥的做法是自己生成文件名,或者只保留安全的 basename:
from pathlib import Path
filename = Path(user_filename).name
path = Path('downloads') / filename如果是公开上传下载系统,还需要检查文件大小、扩展名、MIME 类型和权限,这些可以以后再深入。
总结
网络编程安全的核心是:不信任外部输入、不泄露敏感信息、不关闭重要安全校验、限制请求范围和资源消耗。
- 网络代码会接触外部输入和敏感凭证,默认不要完全信任。
- Token、Cookie、密码不要硬编码,也不要完整写入日志。
- 服务端请求用户提供的 URL、保存用户提供的文件名时,都要特别谨慎。
版权所有
版权归属:Shuo Liu
