Python中如何防止SQL注入?pymysql或其他数据库框架推荐

我是新人,刚学一段时间的 py 一度放弃,今天又看了看 flask

蹑手蹑脚开发出来了基本的 web 网页, 操作到了数据库, 目前使用的 pymysql 以及 DBUtils 作为连接池管理。

但是好像,。 字符串的 format 或者 %s 都不能过滤。。 求指导 求推荐


Python中如何防止SQL注入?pymysql或其他数据库框架推荐
24 回复

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 查询没有真正的参数化查询
参数化效果依赖库的底层字符串拼接实现

望指正

有的,前几天刚写过

预处理不就防注入了

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)

已贴代码

有看您发的博客,学习了


sql = "select * from users where username = ‘%s’ and passwords = ‘%s’"

cur.execute(sql, (username,password))

回到顶部