Python SQLite3库的值插值问题

llew8vvj  于 2023-03-23  发布在  SQLite
关注(0)|答案(2)|浏览(243)

这个问题是来自服务器故障的migrated,因为昨天可以在Stack Overflow.Migrated上回答。
我有一个奇怪的问题与SQL查询,我发现很难调试不幸。
我有一个将用户插入数据库的查询,如果我运行这个调试语句,我会从表单中返回值。

app.logger.debug(f'''{request.form.get("firstName").capitalize()}, {request.form.get("lastName").capitalize()}, {request.form.get("userName").lower()}, {request.form.get("inputEmail").lower()}, {generate_password_hash(request.form.get("inputPassword"), method="sha256")}''')

具体如下

DEBUG: David, Taylor, taylord, dave@imagetaylor.com, sha256$xXfFJg6EKm9V7O5D$f8eadba22c3ad99c4133ac9ae4d2d25dfe9665b70df04d51417d1caec708ab4c

如果我把它们插入到SQL查询中,一切都正常

dbexe("INSERT INTO users(firstname,lastname,username,email,hash) VALUES('David','Taylor','taylord','dave@imagetaylor.com','sha256$04meQSacFSYL12aq$b17d53e8a3de54e0dcf66c11cf36858f551b9b72a771b18c9b8f3bf24599f8b2')")

然而,当我通过sqlite3库使用安全插值时,它福尔斯,我很难找到一种方法来查看这个问题。

dbexe("INSERT INTO users(firstname,lastname,username,email,hash) VALUES('?','?','?','?','?')", request.form.get("firstName").capitalize(), request.form.get("lastName").capitalize(), request.form.get("userName").lower(), request.form.get("inputEmail").lower(), generate_password_hash(request.form.get("inputPassword"), method="sha256"))

dbexec函数如下所示。

def dbexe(query):
    try:
        retval = []
        db = sqlite3.connect("main.db")
        db.row_factory = dict_factory
        for row in db.execute(query):
            retval.append(row)
        db.commit()
        db.close()
    except:
        return "Failed"
    return retval
dffbzjpn

dffbzjpn1#

您的dbexe函数不接受额外的参数,因此您肯定会得到一个TypeError
如果您希望保留dbexe(sql, a, b, c)调用约定,而db.execute()通常需要将占位符参数作为一个元组,那么可以这样做

def dbexe(query, *args):
   ...
   for row in db.execute(query, args):
      ...

我建议去掉try: except:,因为它是,你永远不知道到底出了什么问题,并在with块中打开数据库连接:

def dbexe(query, *args):
    with sqlite3.connect("main.db") as db:
        db.row_factory = dict_factory
        retval = list(db.execute(query, args))
        db.commit()
    return retval

此外,如注解中所述,您不希望引用问号:

dbexe(
    "INSERT INTO users(firstname,lastname,username,email,hash) VALUES(?, ?, ?, ?, ?)",
    request.form.get("firstName").capitalize(),
    request.form.get("lastName").capitalize(),
    request.form.get("userName").lower(),
    request.form.get("inputEmail").lower(),
    generate_password_hash(request.form.get("inputPassword"), method="sha256"),
)
bogh5gae

bogh5gae2#

使用VALUES(?,?,?,?,?)代替VALUES('?','?','?','?','?')
没有安全的插值。代码使用的是带参数的查询,而不是任何类型的字符串插值。?是一个参数,不是格式占位符,不应该用引号括起来。参数 * 值 * 包含在查询本身中。它们作为单独的、将强类型值与查询一起添加到数据库中。然后,数据库将查询编译为参数化的执行计划,使用这些值执行该执行计划。
这样,您就可以将数字、日期或包含任何内容的字符串发送到服务器,而不必担心格式或注入风险。

相关问题