我使用Twisted在Python中异步访问我们的数据库。我的代码如下所示:
from twisted.enterprise import adbapi
from MySQLdb import _mysql as mysql
...
txn.execute("""
INSERT INTO users_accounts_data_snapshots (accountid, programid, fieldid, value, timestamp, jobid)
VALUES ('%s', '%s', '%s', '%s', '%s', '%s')
""" % (accountid, programid, record, mysql.escape_string(newrecordslist[record]), ended, jobid))
这一直有效,直到我遇到这个字符:®,导致该线程抛出异常:`exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\xae' in position 7: ordinal not in range(128)
但是,如果我不使用MySQLdb_mysql.escape_string(),当输入包含引号等(当然)时,我会收到数据库错误。在访问数据库之前发生异常,因此数据库的整理似乎根本不重要。
在不对unicode字符抛出异常的情况下,逃避此内容的最佳方法是什么?理想的解决方案是我可以传递unicode字符,不会干扰查询以及MySQL不受干扰;但是,剥离unicode字符串,用问号替换它们,修改它们或其他任何可以阻止崩溃的东西都是可以接受的。
答案 0 :(得分:11)
不要格式化这样的字符串。这是一个巨大的安全漏洞。不能自己正确引用。不要试试。
使用第二个参数来“执行”。简单地说,不是txn.execute("... %s, %s ..." % ("xxx", "yyy"))
,而是txn.execute("... %s, %s ...", ("xxx", "yyy"))
。请注意逗号而不是百分号。在其他数据库中或使用不同的数据库绑定,您可以使用不同的字符而不是“%s”,例如?
或:1, :2, :3
或:foo:, :bar:, :baz:
,但这个想法是相同的。 (如果您对替代方案感到好奇,可以查看paramstyle in the DB-API 2.0 documentation的文档。)
I've written about this in the past。关于这篇文章的讨论可能对您特别感兴趣。
还请让我强调这是唯一正确的方法。您可能已经看到MySQL文档讨论以各种方式引用字符串。您可能在PHP中编写了应用程序,缺少适当的传递数据库参数的工具。我保证所有这些信息源都不正确并导致严重且持续的安全问题:不要将参数插入到SQL字符串中。
答案 1 :(得分:2)