3关于Python和SQLite的问题

mwecs4sa  于 2022-12-27  发布在  SQLite
关注(0)|答案(2)|浏览(146)

我正在创建一个游戏服务器使用的函数。这个服务器使用插件。我有这些函数使用SQLite数据库,沿着APSW检索由另一个函数存储的项目。我有3个问题。
问题一:我一直收到错误“SQLError:near“?":syntax error”由于我的语句中包含多个?,因此很难找到错误的确切位置。
问题二:我知道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
anhgbhbe

anhgbhbe1#

这很有趣(请继续阅读,了解原因)。
第一条语句实际上使用了sqlite3-模块的值绑定机制(我假设这就是您使用的)。因此,*(默认列)被转义,使语句无效。这是SQL注入证明,您自己的代码尝试注入SQL(现在看到有趣的地方了吗?)
第二次使用Pythons字符串替换来构建查询字符串时,这不是SQL注入证明。

ztigrdn8

ztigrdn82#

使用名称来获取更多信息性的错误消息。例如,我故意在下面的语句中省略了一个逗号:

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字母数字文本。如果您希望限制较少,则需要用引号括起名称。请使用方括号括起包含双引号的名称,并使用双引号括起包含方括号的名称。一个名字不能两者兼得。
这是使用授权者机制的替代方法。请参阅Connection.setauthorizer了解API和一个示例。简单地说,回调函数是用将要执行的操作调用的,例如,您可以拒绝任何写入数据库的操作。
在效率方面,你可以根据调用者使用结果的方式来改进。2游标是非常便宜的。3没有必要一次又一次地重复使用同一个游标,这样做可能会导致细微的错误。4 SQLite只在你请求的时候才得到结果的下一行。5通过使用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还是个新手。我强烈建议你查找迭代器和生成器。这是一种简单得多的编码风格,可以根据需要生成和使用结果。
顺便说一句,这个SQL创建了一个表,表名为零长度,列名为双引号和分号。SQLite功能很好,但不要这样做:-)但它对测试很有用。

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

披露:我是APSW作者

相关问题