3涉及python和sqlite的问题

时间:2010-11-06 19:13:33

标签: python database sqlite

好的,我正在创建用于游戏服务器的功能。此服务器使用插件。我有这些函数使用sqlite数据库,以及apsw来检索由另一个函数存储的项目。我有3个问题。

问题一:我一直收到错误“SQLError:near”?“:语法错误”由于我的语句有多个?,它证明了难以理解的错误。那有什么问题?

问题二:我知道SQL注入,但这些函数只接受来自脚本运行器的输入,而他唯一会损害的是他自己的。即便如此,是否有一种简单的方法可以使这个sql注入证明?

问题三:有没有办法让这个功能更有效率?

这是功能: 编辑:下面是现在的样子:

def readdb(self,entry,column,returncolumn = "id,matbefore,matafter,name,date"):
    self.memwrite
    if isinstance(entry, int) or isinstance(entry, str):
        statement = 'SELECT {0} FROM main WHERE {1} IN {2}'.format(returncolumn,column,entry)
        self.memcursor.execute(statement)
        blockinfo = self.memcursor.fetchall()
        return(blockinfo)
    if isinstance(entry, tuple) or isinstance(entry, list):
        statement = '''SELECT {0} FROM main WHERE {1} IN (%s)'''.format(returncolumn,column)
        self.memcursor.execute(statement % ("?," * len(entry))[:-1], entry)
        blockinfo = self.memcursor.fetchall()
        return(blockinfo

2 个答案:

答案 0 :(得分:3)

这很有趣(请继续阅读以了解原因)。

您实际使用的第一个语句是sqlite3 - 模块的值绑定机制(我假设这是您使用的)。因此,*(默认列)被转义,使语句无效。这是SQL注入证明,你自己的代码试图注入SQL(现在看到有趣的吗?)。

第二次使用Pythons字符串替换来构建查询字符串,这不是SQL注入证明。

答案 1 :(得分:0)

使用名称获取更多信息性错误消息。例如,我特意遗漏了一个逗号:

 cur.execute("select ? ?,?", (1,2,3))
 SQLError: near "?": syntax error

现在有了名字:

 cur.execute("select :1 :2,:3", (1,2,3))
 SQLError: near ":2": syntax error

如果您有很多绑定,我建议您切换到命名绑定样式并为绑定本身传递字典。

cur.execute("select :artist, :painting, :date", 
  {"artist": "Monster", "painting": "The Duck", "date": "10/10/2010" })

您只能对值使用绑定,而不能对列名或表名使用绑定。有几种可能的方法。虽然SQLite支持任意列/表名,但您可以要求它们只是ASCII字母数字文本。如果你想减少限制,那么你需要引用名称。在包含双引号的名称周围使用方括号,并在名称中包含方括号的双引号。名称不能同时具有。

使用授权机制的所有选择的替代方案。有关API和指向示例的指针,请参阅Connection.setauthorizer。简而言之,您将使用将要执行的操作调用回调,例如,您可以拒绝任何可写入数据库的操作。

在效率方面,您可以根据呼叫者如何使用结果来改进。游标非常便宜。没有必要反复尝试重复使用同一个,这样做会导致细微的错误。当您要求时,SQLite仅获取结果的下一行。通过使用fetchall,您坚持要建立所有结果的列表。如果列表可能很大,或者如果您可能会停止,那么只需返回db.cursor().execute("... query ...")。然后调用者应该使用您的函数进行迭代:

for id,matbefore,matafter,name,date in readdb(...):
    ... do something ...

在你的位置我会完全破坏这个readdb函数,因为它不会添加任何值并直接编写查询:

for id,foo,bar in db.cursor().execute("select id,foo,bar from .... where ...."):
    ... do something ...

您的编码风格表明您对Python很新。我强烈建议查找迭代器和生成器。这是一种更简单的编码风格,可以根据需要生成和消耗结果。

BTW此SQL创建一个名称为零的表,以及名为double quote和semicolon的列。 SQLite函数很好,但不要这样做:-)但它对测试很有用。

create table "" (["], ";");

披露:我是APSW作者