簡體   English   中英

如何(安全地)將字典轉換為 Python 中 sqlite 的 UPDATE 語句?

[英]How can I (safely) convert a dictionary into an UPDATE statement for sqlite in Python?

例如,我有一個學生表,我有一個 Python 字典

mydict = {"fname" : "samwise", "lname" : "gamgee", "age" : 13}

如何安全地生成一個 Python function 可以將其更新到我的student表中? (在我的用例中,我可以安全地假設學生已經存在於表中,並且我已經知道id

我創建了一個實現此功能的 function,但我不禁認為它有點粗糙,可能對 SQL 注入攻擊持開放態度

def sqlite_update(conn, table, data, pkeyname, pkeyval):
    set_lines = ""
    for k,v in data.items():
        set_lines += "{} = '{}', ".format(k,v)

    set_lines = set_lines[:-2] #remove space and comma from last item

    sql = "UPDATE {0} SET {1} WHERE {2} = '{3}'"
    statement = sql.format(table, set_lines, pkeyname, pkeyval)

    conn.execute(statement)
    conn.commit()

更新我只是打電話

sqlite_update(conn, "student", mydict, "id", 1)

正如我假設您正在使用sqlalchemy 在這種情況下,您可以使用sqlalchemy.sql.text function 如果需要,它會轉義字符串。

您可以嘗試如下調整您的 function。

from sqlalchemy.sql import text

def sqlite_update(conn, table, data, pkeyname, pkeyval):
    set_lines = ",".join([f"{k}=:{k}" for k in data.keys()])
    statement = text(f"UPDATE {table} SET {set_lines} WHERE {pkeyname} = :pkeyval")

    args = dict(data)
    args["pkeyval"] = pkeyval
    conn.execute(statement, args)
    conn.commit()

更多詳情請參考sqlalchemy官方文檔function。

編輯

至於 sqlite3 連接,您可以做與上面基本相同的事情,只需稍作改動。

def sqlite_update(conn, table, data, pkeyname, pkeyval):
    set_lines = ",".join([f"{k}=:{k}" for k in data.keys()])
    statement = f"UPDATE {table} SET {set_lines} WHERE {pkeyname} = :pkeyval"

    args = dict(data)
    args["pkeyval"] = pkeyval
    conn.execute(statement, args)
    conn.commit()

參考 sqlite3 執行

這確實對 SQL 注入廣泛開放,因為您將查詢構建為包含其值的字符串,而不是使用參數化查詢。

使用 Python 構建參數化查詢很容易:

def sqlite_update(conn, table, data, pkeyname, pkeyval):
    query = f"UPDATE {table} SET " + ', '.join(
        "{}=?".format(k) for k in data.keys()) + f" WHERE {pkeyname}=?"
    # uncomment next line for debugging
    # print(query, list(data.values()) + [pkeyval])
    conn.execute(query, list(data.values()) + [pkeyval])

在您的示例中,調試print行顯示的查詢是:

UPDATE student SET fname=?, lname=?, age=? WHERE id=?

具有以下值列表: ['samwise', 'gamgee', 13, 1]

但請注意,要完全防止 SQL 注入,您應該清理表和字段名稱以確保它們不包含危險字符,例如;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM