flawopen.com/Python 中的 SQL 注入/SQLAlchemy
SQLAlchemy text() 能防止 SQL 注入吗?
参考指南
简短回答
绑定参数就像查询表单中密封的值卡:SQLAlchemy 会把 SQL 语句及其参数映射传给底层 DBAPI,使值不进入应用代码构造的 SQL 表达式。DBAPI 驱动负责数据库特定的绑定,因此在线路上的传输方式可能不同。text() 接受 SQL 文本,但不会清理或参数化已经插入其中的值。
不安全 — 将输入插值进 SQL
stmt = text(
f"SELECT id FROM users WHERE id = {user_id}"
)
rows = conn.execute(stmt)
加固 — 绑定值并限制 SQL 结构
stmt = text(
"SELECT id FROM users WHERE id = :id"
)
rows = conn.execute(stmt, {"id": user_id})
# Bind values, not identifiers. Choose any
# selectable column from a fixed application map.
columns = {"name": users.c.name,
"created": users.c.created_at}
column = columns.get(requested_sort, users.c.created_at)
stmt = select(users.c.id).order_by(column)
rows = conn.execute(stmt)
text() 能做什么 — 不能做什么
text() 创建文本 SQL 结构,但不会清理已经包含插值输入的字符串。应在 SQL 中声明值占位符,再将值单独传给 Connection.execute() 或 Session.execute()。SQLAlchemy Core 表达式 API 会在适当场景绑定 Python 字面值,但文本片段仍是 SQL 语法。参数不能替代表名、列名或排序方向。将用户选择的结构映射到固定的 SQLAlchemy 表达式。参数化可防止 SQL 注入,但不能替代授权或业务规则验证。
如何审查代码库
rg -n 'text\(|\.execute\(' --glob '*.py' .常见问题
SQLAlchemy Core 和 ORM 查询构造器总是安全吗?
在常规表达式构造中,它们会绑定 Python 值,但安全性取决于语句的构造方式。还要审查文本 SQL、字面 SQL 构造和动态标识符。任何 API 都无法在输入已经拼接进 SQL 字符串后使其安全。