【问题标题】:How to refactor my python to use a SQL Prepared statement?如何重构我的 python 以使用 SQL Prepared 语句?
【发布时间】:2020-11-06 18:08:17
【问题描述】:

接受用户输入并为用户提供给定用户名的代码。现在它直接接受输入到 SQL 查询中,但我想将它与准备好的语句一起使用,我该怎么做?

# SELECT QUERIES
def get_all_results(q):
    cur = mysql.connection.cursor()
    cur.execute(q)
    mysql.connection.commit()
    data = cur.fetchall()
    cur.close()
    return data


# UPDATE and INSERT QUERIES
def commit_results(q):
    cur = mysql.connection.cursor()
    cur.execute(q)
    mysql.connection.commit()
    cur.close()


##### Returns a user for a given username
### in: username
### out: User
def get_user(username):
    q = "SELECT * FROM Users"
    q+= " WHERE username = '%s'" % (username)
    logging.debug("get_user query: %s" % q)
    data = get_all_results(q)

    if len(data) == 1:
        user = User(*(data[0]))
        return user
    else:
        logging.debug("get_user: Something wrong happened with (username):(%s)" % (username))
        return None```

【问题讨论】:

  • 字符串取模%,格式化方式为无longer recommended in Python,应替换为str.format(v2.6+)或F-strings(v3.6+)。跨度>
  • 即使使用str.format() 也不是执行准备好的语句的方法。如果您自己将变量插入 SQL 查询字符串,无论您使用哪种字符串格式样式,这都无助于防止 SQL 注入。

标签: python mysql sql sql-injection


【解决方案1】:

考虑调整您的查询方法以接受参数输入并在cursor.execute 中运行。这需要您替换 SQL 字符串中数据值的字符串格式

" WHERE username = '%s'" % (username)

带有一个没有数据的预准备语句,该语句稍后通过参数与数据绑定。

" WHERE username = %s"

不要将不带引号的%s 与带引号的'%s' 占位符混淆(Python 中不再推荐使用上述后一种方法)。总而言之:

# SELECT QUERIES
def get_all_results(q, p):                          # ADD NEW INPUT PARAMETER 
    cur = mysql.connection.cursor()
    cur.execute(q, p)                               # PASS BOTH IN EXECUTE CALL
    mysql.connection.commit()
    data = cur.fetchall()
    cur.close()
    return data

# UPDATE and INSERT QUERIES
def commit_results(q, p):                           # ADD NEW INPUT PARAMETER 
    cur = mysql.connection.cursor()
    cur.execute(q, p)                               # PASS BOTH IN EXECUTE CALL
    mysql.connection.commit()
    cur.close()

def get_user(username):
    q = "SELECT * FROM Users WHERE username = %s"   # PREPARED STATEMENT

    logging.debug("get_user query: {}".format(q))

    data = get_all_results(q, (username,))          # PASS PARAMETER AS TUPLE
    # data = get_all_results(q, [username])         # PASS PARAMETER AS LIST

    if len(data) == 1:
        user = User(*(data[0]))
    else:
        msg = "get_user: Something wrong happened with username:{}".format(username)
        logging.debug(msg)
        user = None

    return user

如果调用不需要参数,则传递None 类型。

data = get_all_results(q, None)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-26
    • 1970-01-01
    • 2019-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多