在 Python 中使用 MySQLdb 执行这样的 SQL 查询是否安全?
我注意到大多数消息来源都说在 Python 中执行 SQL 语句的最佳实践是这样的:
cursor.execute( 'select * from coworkers where name = :1 and clue > :2', [ name, clue_threshold ] )
其他消息来源说
cursor.execute( "select * from coworkers where name = %s and clue > %s", ( name, clue_threshold ) )
我认为这非常相似。
无论如何,我一直在做的方式是创建字典并存储值。例如,初始字典 biz_info
看起来像这样:
biz_info = {
'business' : None,
'name' : None,
'neighborhood' : None,
'address' : None,
'city' : None,
'state' : None,
'zip_code' : None,
'latitude' : None,
'longitude' : None,
'phone' : None,
'url' : None,
'yelp_url' : None,
}
然后我执行这样的 SQL 语句
execute_sql( cur, "insert into " + TABLE_BIZ_NAME + """ values (
NULL,
%(name)s,
%(neighborhood)s,
%(address)s,
%(city)s,
%(state)s,
%(zip_code)s,
%(latitude)s,
%(longitude)s,
%(phone)s,
%(url)s,
%(yelp_url)s,
NULL
)"""
, biz_info )
这对于 sql 注入安全吗?我想使用字典来存储信息,因为它更容易管理。
老实说,我什至不完全确定使用 %
、、
、%s
、%d 之间有什么区别
和 %()s
表示参数化查询。基本上我所知道的是不使用
cursor.execute( "select * from coworkers where name = '%s' and clue > %d" % ( name, clue_threshold ) )
I've notice most sources say to best practice to execute SQL statements in Python is something like this:
cursor.execute( 'select * from coworkers where name = :1 and clue > :2', [ name, clue_threshold ] )
Other sources say
cursor.execute( "select * from coworkers where name = %s and clue > %s", ( name, clue_threshold ) )
which I think is pretty similar.
Anyway the way I have been doing is creating a dictionary and storing values. For example, the initial dictionary biz_info
looks like this:
biz_info = {
'business' : None,
'name' : None,
'neighborhood' : None,
'address' : None,
'city' : None,
'state' : None,
'zip_code' : None,
'latitude' : None,
'longitude' : None,
'phone' : None,
'url' : None,
'yelp_url' : None,
}
then I execute the SQL statement like this
execute_sql( cur, "insert into " + TABLE_BIZ_NAME + """ values (
NULL,
%(name)s,
%(neighborhood)s,
%(address)s,
%(city)s,
%(state)s,
%(zip_code)s,
%(latitude)s,
%(longitude)s,
%(phone)s,
%(url)s,
%(yelp_url)s,
NULL
)"""
, biz_info )
Is this safe against sql injections? I want to use dictionaries to store information because it's easier to manage.
To be honest, I'm not even entirely sure what the difference between using a %
, ,
, %s
, %d
, and %()s
means in parameterized queries. Basically all I know is not to use
cursor.execute( "select * from coworkers where name = '%s' and clue > %d" % ( name, clue_threshold ) )
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
将参数传递给 sql 命令字符串的方式取决于数据库(例如,sqlite 使用
?
)。根据MySQLdb文档,可以使用
paramstyle
参数来设置格式化字符串的首选方式(format
或pyformat
)。您问题中的第一个示例似乎不受支持。无论如何,我想说,只要您不像上一个示例那样格式化整个字符串,您就是安全的,因为可以假设查询参数将被正确转义。
The way used to pass parameters to sql command strings depends on the database (sqlite, for example, uses
?
).According to MySQLdb documentation, you can use
paramstyle
parameter to set the preferred way to format a string (format
orpyformat
).The first example in your question doesn't seem to be supported. Anyway, I'd say that as long as you don't format the whole string as in the last example, you're safe since it can be assumed that the query parameters will be properly escaped.
您的插入语句应该真正明确地指定要设置的字段名称,以防止架构更改造成破坏。另外,我发现您的代码过于重复。我会编写类似于这样的插入内容:
这样,在创建 biz_info 字典时,字段名称只需要列出一次。未来的任何变化只需要在那里更新即可。
Your insert statement should really explicitly specify the field names to be set, to guard against breakages from schema changes. Also, I find your code too repetitive. I would write the insert something more like this:
This way, the field names only need to be listed once, in the creation of the biz_info dict. And any future changes only need them to be updated there.