Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在pyodbc中从用户处获取表名,同时避免SQL注入?_Python_Sql_Sql Server_Python 3.x_Pyodbc - Fatal编程技术网

Python 如何在pyodbc中从用户处获取表名,同时避免SQL注入?

Python 如何在pyodbc中从用户处获取表名,同时避免SQL注入?,python,sql,sql-server,python-3.x,pyodbc,Python,Sql,Sql Server,Python 3.x,Pyodbc,我有下面的代码,它是完全安全的,用户不能输入任何可能导致SQL注入的内容 value = get_value_from_user_input() query = \ """ SELECT * FROM TestTable WHERE CompareValue = ? """ cursor.execute(query, value) 但是,如果我需要从用户那里获取表名,该怎么办呢。我不能这样做,因为这让我很容易受到SQL注入的影响 table_name =

我有下面的代码,它是完全安全的,用户不能输入任何可能导致SQL注入的内容

value = get_value_from_user_input()
query = \
    """
    SELECT *
    FROM TestTable
    WHERE CompareValue = ?
    """
cursor.execute(query, value)
但是,如果我需要从用户那里获取表名,该怎么办呢。我不能这样做,因为这让我很容易受到SQL注入的影响

table_name = get_table_name_from_user_input()
query = \
    f"""
    SELECT *
    FROM {table_name}
    WHERE CompareValue = 1234
    """
cursor.execute(query)
我也不能这样做(在我看来这是合乎逻辑的),因为它会给出一个错误

table_name = get_table_name_from_user_input()
query = \
    """
    SELECT *
    FROM ?
    WHERE CompareValue = 1234
    """
cursor.execute(query, table_name)
那我该怎么做呢

额外信息:


该程序是在我的公司内部使用的,软件的所有用户都有数据库的管理员权限。不允许它们注入SQL可能有点毫无意义,因为它们无论如何都可以执行原始SQL查询。我只是想学究一点,不允许我的程序执行随机SQL。
get\u table\u name\u from\u user\u input()
实际上是从描述数据库结构的配置文件中获取表名,因此,如果有一天数据库中的表名发生更改,用户可以轻松地对其进行编辑,而无需接触源代码。

如果没有太多的表,您可以检查请求的表名是否存在于有效表名列表中

tables = ["customers", "vendors", "products"]

user_inputs = ["products", "invoices", "vendors WHERE CompareValue=1234; DROP TABLE customers; --"]

query = "SELECT * FROM placeholder WHERE CompareValue=1234;"

for user_input in user_inputs:
  if user_input in tables:
    print(query.replace("placeholder", user_input))
  else:
    print(f"'{user_input}' is not a valid table")
给出了以下结果

SELECT * FROM products WHERE CompareValue=1234;
'invoices' is not a valid table
'vendors WHERE CompareValue=1234; DROP TABLE customers; --' is not a valid table

repl:

中的此代码段您可以使用pyodbc的函数直接从数据库中获取有效表名的列表:

crsr=cnxn.cursor()
表_name=[x[2]表示crsr.tables中的x(tableType='table')]
打印(表格名称)#[‘客户’、‘发票’、…]
如前所述,您不能使用参数为查询提供对象(例如表或列)名称,但可以使用t-SQL函数帮助确保您构造的(动态)SQL有效


关注可能的SQL注入问题是好事,但并非所有动态SQL都是坏事。有时,就像在这种情况下,这是必要的;你只需要采取适当的措施来保护自己。

如果你阅读了我的“附加信息”部分,这就解释了为什么我不能这样做。我想要一种从数据库本身检查有效性的方法。