QT5 的QSqlDatabase 防止SQL注入

本文介绍了如何在Python中使用PyQt5的QSqlQuery模块避免SQL注入问题,通过prepare()和bindValue()方法正确处理参数,确保代码安全。重点讲解了addBindValue()和bindValue()的用法以及它们在执行SQL查询时的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用拼接字符串方式构造SQL语句比较容易犯sql注入问题。

常见的防范方式是以参数传入的方式处理,(把参数通过数据库提供的接口传入数据库,在数据库里面处理,而不是在数据库外面拼接SQL语句)

python 中一般是在游标执行execute时传递参数

uid=123
pwd='bb987#$!~EE' 
args = (uid, pwd)
cur.execute('select * from user_table where uid = %s and pwd = %s', args )

注意:

对于传入的字符串类型的参数,在构造sql语句的模板上不需要加引号,mysql会自动转义及加引号的。

但对于string.format(参数值,参数值) 和 string % (参数值,参数值) 方式先把sql生成好再直接执行的方式,是需要手动加引号的。

uid=100
pwd='976$#@387'
cur.execute(“select * from user_table where uid = %s and pwd = %s”, (uid,pwd) )

# 上面这句pwd位置不需要加引号,sql模板和值之间是用逗号【分隔】。
# 下面这句pwd位置需要加引号,   sql模板和值之间是用百分号【连接】。

cur.execute(“select * from user_table where uid = %s and pwd = '%s'” % (uid,pwd) )

但QT5的QsqlQuery的exec函数不支持这种方式。提示:too many arguments

建议使用QSqlQuery.prepare  官方文档:QSqlQuery — Qt for Python

在PyQt中,prepare()可以保护你免受SQL注入攻击,当你的SQL语句含有不可信输入时,推荐使用prepare。

exec(QString query): 执行query查询语句。查询执行后,必须通过使用next()等函数,定位到一个有效的记录,才能读取数据库记录。
prepare(QString query): 准备SQL查询语句。适用于带参数的查询语句。查询代码中的参数可以用ODBC样式(问号)或Oracle样式(符号前面加冒号)来指定,但是它们不能混合在同一个查询中。
addBindValue(QVariant val[, QSql.ParamType paramType = QSql.In]):使用位置值绑定时,将值val添加到值列表中。 addBindValue( )调用的顺序决定了此值 绑定到prepare()函数参数中的哪个占位符。

可选参数paramType 默认值为QSql.In,表明是往数据库中写入数据;

QSql.Out为从数据库中读出数据;

QSql.InOut为往数据库中写入数据,但执行exec()后,会被读出的数据覆盖。

要绑定NULL值,请使用空QVariant;例如,如果要绑定字符串,请使用QVariant(QVariant::String)。

bindValue(int pos, const QVariant val, QSql.ParamType paramType = QSql.In):指定prepare()函数参数中的pos占位符的值为val。pos=0代表第一个占位符。

bindValue(placeholderval[, type=QSql.In])

传入参数值的方法有两个:addBindValue() 和 bindValue()  区别在于addBindValue()必须严格按照顺序传入,bindValue()可以不按顺序,因为通过pos参数 或 placeholder参数指定了传给谁。

# addBindValue(const QVariant val, QSql.ParamType paramType = QSql.In):调用的顺序决定了此值 绑定到prepare()函数参数中的哪个占位符。

     query.prepare ("insert into good values (null,?,?)")
     query.addBindValue ('Floppy')
     query.addBindValue (10)
     query.exec()


# bindValue(int pos, const QVariant val, QSql.ParamType paramType = QSql.In):指定prepare()函数参数中的pos占位符的值为val。pos=0代表第一个占位符。

     query.prepare ("insert into good values (null,?,?)")
     query.bindValue (0, 'Floppy')
     query.bindValue (1, 10)
     query.exec()

# bindValue(QString placehold, const QVariant val, QSql.ParamType paramType = QSql.In):指定prepare()函数参数中的placehold占位符的值为val。 

      query .prepare("insert into good values(null,  :name,  : count )")
      query.bindValue(":name",   'Floppy')
      query.bindValue(":count", 10)
      query.exec()

# exec():执行prepare()中的SQL语句。 如果执行成功,返回True; 否则,返回False。

 官方文档代码example:

query = QSqlQuery()
query.prepare("INSERT INTO person (id, forename, surname) "
              "VALUES (:id, :forename, :surname)")
query.bindValue(":id", 1001)
query.bindValue(":forename", "Bart")
query.bindValue(":surname", "Simpson")
query.exec_()

补充:

经测试,同一个QSqlQuery对象,重新执行prepare后,之前绑定的value就全部失效了。

但在不重新执行prepare情况下,重新绑定value,然后重新执行exec_(),会得到新的结果。

sql="select * from user_table where id=?"
myQuery =QSqlQuery()
myQuery.prepare(sql)
myQuery.addBindValue(100)
myQuery.exec_()

while myQuery.next():
    print(myQuery.value('user_name'))


# 没有重新prepare,直接重新addBindValue,再次执行exec_(),得到新结果
myQuery.addBindValue(102)
myQuery.exec_()

while myQuery.next():
    print(myQuery.value('user_name'))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值