Python输入校验怎么做_安全编码实践

2次阅读

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

Python输入校验怎么做_安全编码实践

Python输入校验的核心是“不信任任何外部输入”,必须在使用前明确验证类型、范围、格式和语义。重点不是“拦住所有坏输入”,而是“只接受明确允许的输入”,并配合安全的处理方式(如参数化查询、白名单过滤、上下文感知转义)。

类型与基础结构校验

避免用 try/except 捕获类型错误来“试探”输入,应主动检查。例如接收数字时,先判断是否为字符串再调用 str.isdigit()str.isdecimal()(注意负数、小数需额外处理),或直接用 ast.literal_eval() 安全解析字面量。

  • 对用户传入的 ID、年龄等整数字段,用 str.strip() 去空格后检查是否匹配正则 r'^d+$',再转 int
  • 邮箱、URL 等格式用标准库 email-validatorurllib.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、字段名),但绝不记录原始敏感输入值
text=ZqhQzanResources