python输入校验核心是“只接受明确允许的输入”,需严格验证类型、范围、格式、语义,并配合参数化查询、白名单过滤、上下文转义等安全处理;推荐用pydantic统一建模与校验,失败时返回无泄漏错误并记录日志。

Python输入校验的核心是“不信任任何外部输入”,必须在使用前明确验证类型、范围、格式和语义。重点不是“拦住所有坏输入”,而是“只接受明确允许的输入”,并配合安全的处理方式(如参数化查询、白名单过滤、上下文感知转义)。
类型与基础结构校验
避免用 try/except 捕获类型错误来“试探”输入,应主动检查。例如接收数字时,先判断是否为字符串再调用 str.isdigit() 或 str.isdecimal()(注意负数、小数需额外处理),或直接用 ast.literal_eval() 安全解析字面量。
- 对用户传入的 ID、年龄等整数字段,用
str.strip()去空格后检查是否匹配正则r'^\d+$',再转int - 邮箱、URL 等格式用标准库
email-validator或urllib.parse.urlparse()验证结构,而非仅靠正则粗筛 - JSON 输入务必用
json.loads()解析,并捕获JSONDecodeError;禁止用eval()或exec()
业务逻辑与白名单约束
校验必须落到具体业务场景。比如一个状态字段只允许 "active"、"inactive"、"pending",就该硬编码白名单比对,而不是只检查是否为字符串。
- 枚举类(
Enum)定义合法值,校验时用in MyEnum.__members__或isinstance(val, MyEnum) - 文件上传时,不仅检查后缀名(易伪造),更要读取文件头(magic bytes)确认真实 MIME 类型
- 路径拼接前,用
os.path.normpath()标准化,再检查是否仍在预期目录内(如path.startswith('/var/www/uploads'))
防范注入与上下文转义
校验只是第一道防线,后续使用环节必须按上下文做安全处理:数据库查询用参数化(sqlite3 的 ? 占位符、psycopg2 的 %s),HTML 输出用 html.escape(),Shell 命令避免拼接,改用 subprocess.run([...], shell=False)。
立即学习“Python免费学习笔记(深入)”;
- SQL 查询中,表名、列名等无法参数化的部分,只能通过白名单映射(如
{"sort_by": "created_at"}→ 实际用"created_at") - 模板渲染(Jinja2/Django)默认已转义,但若需输出 HTML 内容,应明确标记
|safe并确保内容已由可信来源生成 - 调用外部 API 时,将用户输入作为请求体 JSON 字段即可,无需额外转义;但作为 URL 查询参数时,必须用
urllib.parse.quote()
统一入口与可维护性设计
避免在每个视图或函数里重复写校验逻辑。推荐用 Pydantic 模型定义输入 Schema,自动完成类型转换、范围限制(@field_validator)、自定义规则(如密码强度)和错误聚合。
- FastAPI 默认集成 Pydantic,Flask 可用
flask-pydantic或手动调用MyModel.model_validate(request.json) - 校验失败时返回清晰、无泄漏的错误信息(如 “邮箱格式不正确”,而非 “ValidationError: value is not a valid email address”)
- 日志记录校验失败事件(含时间、IP、字段名),但绝不记录原始敏感输入值










