Python中如何防止SQL注入?pymysql或其他数据库框架推荐
我是新人,刚学一段时间的 py 一度放弃,今天又看了看 flask
蹑手蹑脚开发出来了基本的 web 网页, 操作到了数据库, 目前使用的 pymysql 以及 DBUtils 作为连接池管理。
但是好像,。 字符串的 format 或者 %s 都不能过滤。。 求指导 求推荐
Python中如何防止SQL注入?pymysql或其他数据库框架推荐
orm 了解下
帖子回复:
防SQL注入的核心就一条:永远别用字符串拼接SQL,必须用参数化查询。
以pymysql为例,看对比:
❌ 错误做法(字符串拼接):
user_input = "admin' OR '1'='1"
sql = f"SELECT * FROM users WHERE username = '{user_input}'"
cursor.execute(sql) # 直接注入成功
✅ 正确做法(参数化查询):
user_input = "admin' OR '1'='1"
sql = "SELECT * FROM users WHERE username = %s"
cursor.execute(sql, (user_input,)) # 输入会被安全转义
关键点:
- pymysql用
%s作占位符(即使非字符串类型) - 参数必须是元组/列表:
(value,)或[value] - 框架会自动处理转义和类型转换
其他框架示例:
SQLAlchemy:
from sqlalchemy import text
stmt = text("SELECT * FROM users WHERE username = :name")
result = conn.execute(stmt, {"name": user_input})
psycopg2(PostgreSQL):
cursor.execute("SELECT * FROM users WHERE username = %s", (user_input,))
sqlite3:
cursor.execute("SELECT * FROM users WHERE username = ?", (user_input,))
框架推荐:
- 简单项目:直接用pymysql/psycopg2 + 参数化查询
- ORM需求:SQLAlchemy(自带防注入)
- 异步:aiomysql/asyncpg
- 类型安全:SQLModel(基于SQLAlchemy+Pydantic)
一句话总结:用参数化查询就完事了,别自己拼字符串。
关键字:参数化查询
刚开始学真的不用考虑这么多 先把程序写出来再考虑其他吧
参数化查询或者 ORM
另外如果是手写的 SQL,参数化查询也不一定是保险的,
表名,limit order by offset 这些记得用白名单或者强制转整形
请贴代码,很多人用 pymsql 直接拼接字符串的
%s 不行?
印象中。。python 的 mysql 查询没有真正的参数化查询
参数化效果依赖库的底层字符串拼接实现
望指正
有的,前几天刚写过
https://blog.dfen.xyz/2018/04/sql-injection.html?m=1
放在 Blogger 上的,要过墙
预处理不就防注入了
flask-sqlalchemy
这个库的底层依旧是拼接,只是过了一层转义
和真正的参数化查询有区别
看了一下代码实现确实如此,这就很尴尬了。各个地方都这么介绍,我还以为是标准的预处理…
如果是不含 ORM 组件的 web 框架可以使用 sqlalchemy。
另外问一下各位,使用 pymysql 的的时候,我在执行 sql 前强制检测单引号并转义,是不是能防止注入?
我是用 re 预处理,如果含有特殊字符就直接返回
这个拼接的感觉还是有些风险,有些 SQL 注入对检测转义绕过方式就是使用编码,对检测的要求非常高
编码?就是 utf-8 gbk 这样的?我昨天查了下资料…要检测编码也是很难,有些编码,有重合…
贴不了图额。。。
if request.method == ‘POST’:
form = request.form
username = form.get(‘username’)
password = form.get(‘password’)
pool = SingletonDBPool()
con = pool.connect()
cur = con.cursor()
sql = “select * from users where username = ‘%s’ and passwords = ‘%s’” % (username,password)
print(sql)
cur.execute(sql)
result = cur.fetchone()
con.commit()
con.close()
print(result)
已贴代码
有看您发的博客,学习了
https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursorprepared.html
官方客户端 现在支持服务端的 prepared
sql = "select * from users where username = ‘%s’ and passwords = ‘%s’"
cur.execute(sql, (username,password))

