在Python sqlite3查询中替换列名

时间:2016-02-11 16:54:30

标签: python security sqlite

我在sqlite3数据库中有一个宽表,我希望动态查询Python脚本中的某些列。我知道it's bad to inject parameters by string concatenation,所以我尝试使用参数替换。

我发现,当我使用参数替换来提供列名时,我会得到意想不到的结果。一个最小的例子:

import sqlite3 as lite

db = lite.connect("mre.sqlite")
c = db.cursor()

# Insert some dummy rows
c.execute("CREATE TABLE trouble (value real)")
c.execute("INSERT INTO trouble (value) VALUES (2)")
c.execute("INSERT INTO trouble (value) VALUES (4)")
db.commit()


for row in c.execute("SELECT AVG(value) FROM trouble"):
    print row   # Returns 3

for row in c.execute("SELECT AVG(:name) FROM trouble", {"name" : "value"}):
    print row   # Returns 0

db.close()

有没有更好的方法来实现这一点,而不仅仅是将一个列名注入一个字符串并运行它?

2 个答案:

答案 0 :(得分:1)

正如罗布刚在评论中指出的那样,有一篇相关的SO帖子包含了我的答案。这些替换结构被称为"占位符,"这就是我最初没有在SO上找到答案的原因。列名没有占位符模式,因为dynamically specifying columns is not a code safety issue

  

归结为" safe"手段。传统观点是这样的   使用普通的python字符串操作将值放入您的   查询不安全"。这是因为有各种各样的事情   如果你这样做可能会出错,这些数据往往来自   用户并不在你的掌控之中。你需要100%可靠的方式   正确地转义这些值,以便用户无法在SQL中注入SQL   数据值并让数据库执行它。所以图书馆作家呢   这个工作;你永远不应该。

     

但是,如果您正在编写通用帮助程序代码来操作事物   在数据库中,这些考虑因素并不适用。你是   隐含地给任何可以调用此类代码的人访问所有内容   在数据库中;这是助手代码的重点。所以现在   安全问题是确保用户生成的数据永远不会   用在这样的代码中。这是编码中的一般安全问题,而且是   与盲目地执行用户输入字符串相同的问题。这是一个   将值插入查询的明显问题,因为那里   您希望能够安全地处理用户输入数据。

所以,解决方案是首先没有问题:使用字符串格式注入值,快乐,继续你的生活。

答案 1 :(得分:0)

为什么不使用字符串格式?

for row in c.execute("SELECT AVG({name}) FROM trouble".format(**{"name" : "value"})):
    print row # => (3.0,)