使用psycopg2/Python DB-API和PostgreSQL进行参数化查询

jef*_*150 43 python postgresql psycopg2

使psycopg2将参数化查询传递给PostgreSQL的最佳方法是什么?我不想编写自己的escpaing机制或适配器,psycopg2源代码和示例很难在Web浏览器中阅读.

如果我需要切换到类似PyGreSQL或其他python pg适配器的东西,那对我来说没问题.我只想要简单的参数化.

Han*_*Gay 79

psycopg2遵循DB-API 2.0的规则(在PEP-249中设置).这意味着您可以executecursor对象调用方法并使用pyformat绑定样式,它将为您执行转义.例如,以下应该是安全的(并且工作):

cursor.execute("SELECT * FROM student WHERE last_name = %(lname)s", 
               {"lname": "Robert'); DROP TABLE students;--"})
Run Code Online (Sandbox Code Playgroud)

  • 好消息是,由于该表名为“student”,而不是“students”;即使代码不安全,它也会失败。给你们黑帽的教训:测试你们的攻击! (7认同)
  • 它没有@ mascot6699,因为查询是参数化的. (4认同)
  • 上面的代码也是如此.是不是丢了桌子? (3认同)

Fáb*_*ias 18

来自psycopg文档

(http://initd.org/psycopg/docs/usage.html)

警告永远不要,永远不要使用Python字符串连接(+)或字符串参数插值(%)将变量传递给SQL查询字符串.甚至在枪口下也没有.

在SQL命令中传递变量的正确方法是使用execute()方法的第二个参数:

SQL = "INSERT INTO authors (name) VALUES (%s);" # Note: no quotes

data = ("O'Reilly", )

cur.execute(SQL, data) # Note: no % operator


ada*_*dam 9

以下是您可能会发现有用的一些示例

cursor.execute('SELECT * from table where id = %(some_id)d', {'some_id': 1234})
Run Code Online (Sandbox Code Playgroud)

或者,您可以根据字段名称,值的动态构建查询:

fields = ', '.join(my_dict.keys())
values = ', '.join(['%%(%s)s' % x for x in my_dict])
query = 'INSERT INTO some_table (%s) VALUES (%s)' % (fields, values)
cursor.execute(query, my_dict)
Run Code Online (Sandbox Code Playgroud)

注意:必须在代码中定义字段,而不是用户输入,否则您将容易受到SQL注入的影响.

  • 因为建议让你对SQL注入开放而被低估了 (11认同)
  • 除非你知道你在做什么,否则你只需要输入sql查询,因为它是一个SQL注入. (9认同)
  • 也就是说,在一般情况下,它使您可以进行SQL注入。 (3认同)
  • @RandySyring如果没有明确定义密钥和正确的标识符,则只对SQL注入开放.这些值仍然适当地参数化. (2认同)