好的,我正在创建用于游戏服务器的功能。此服务器使用插件。我有这些函数使用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
答案 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作者