长度校验无法防御SQL注入,因攻击载荷如' OR 1=1 -- 仅12字符即有效;唯一可靠方案是参数化查询+类型绑定,如psycopg2用%s占位、JDBC用PreparedStatement、pg用$1参数,禁用字符串拼接。

为什么只做长度校验根本防不住SQL注入
长度校验对SQL注入毫无防御作用——攻击载荷可以很短,比如 ' OR 1=1 -- 只有12个字符,远低于常见字段长度限制(如username VARCHAR(50))。它顶多拦住超长垃圾输入,但所有有效攻击向量都在合法长度范围内。
真正该用的防御手段:参数化查询 + 类型绑定
SQL注入的本质是代码与数据混淆。唯一可靠方案是让数据库引擎明确区分“SQL结构”和“用户数据”,这必须靠驱动层支持的参数化机制,不是应用层字符串处理能解决的。
- Python +
psycopg2:必须用cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)),绝不用f"WHERE id = {user_id}" - Java + JDBC:必须用
PreparedStatement,调用setString(1, userInput),而非statement.executeQuery("WHERE name = '" + name + "'") - Node.js +
pg:必须用client.query("SELECT * FROM posts WHERE slug = $1", [slug]),禁用字符串拼接
长度校验还有啥用?仅限业务逻辑兜底
它属于数据合理性检查,和安全无关,但能提前暴露异常输入或前端绕过验证的行为。
- 对
phone字段设MAX_LENGTH=11,可快速发现传入了100个数字的恶意试探 - 对
email字段设MAX_LENGTH=254(RFC 5321上限),避免存储超长字符串导致索引膨胀或截断 - 注意:校验必须在服务端做,前端
maxlength属性完全可被绕过
容易被忽略的陷阱:ORM也未必安全
很多开发者以为用了SQLAlchemy或Django ORM就高枕无忧,但直接拼接仍会发生:
-
session.execute(f"SELECT * FROM logs WHERE level = '{level}'")—— 错!用了f-string -
MyModel.objects.extra(where=[f"status = '{status}'"])(Django)—— 错!extra()不自动转义 - 正确写法:
MyModel.objects.filter(status=status)或session.execute(text("... WHERE level = :level"), {"level": level})
参数化不是“用了ORM就自动生效”,而是取决于你调用的具体API是否接受独立参数对象。任何带f"、+、%拼接SQL字符串的地方,都等于裸奔。











