формат переменных psycopg2 для создания запросов


Это не так важно, поэтому мне просто интересно следующее (Python 2.7):

Я только начал использовать psycopg и читать документы, в которых всегда используются строки (%s) и кортежи для передачи значений в запрос.

Заполнителем переменных всегда должен быть %s

Итак, рассматривая следующий пример -

В таблице с именем 'test' с полями value_1 (varchar) и value_2 (int) создается запрос в виде:

value_1 = "test"
value_2 = "100"
cur.execute("INSERT INTO test (value_1,value_2) VALUES (%s,%s)",
           (value_1,value_2))

Мой вопрос, если это плохая практика или даже проблематично использовать метод "формат" вместо этого (как показано ниже):

cur.execute("INSERT INTO test (value_1,value_2) VALUES ('{value1}',{value2})".
           format(value1=value_1,value2=value_2))
Что вы скажете, основываясь на своем опыте, действительно ли это опасно или проблематично?
3 5

3 ответа:

Вызов

cur.execute("INSERT INTO test (value_1,value_2) VALUES (%s,%s)",\
           (value_1,value_2))

Имеет строковый параметр и дополнительный параметр, представляющий собой кортеж значений для подстановки. Это позволяет psycopg2 интерполировать значения, и делать это более безопасно, чем простая строковая интерполяция.

Документы по использованию для psycopg2 говорят

♯ передайте данные для заполнения заполнителей запроса и позвольте Psycopg выполнить

& sharp; правильное преобразование (больше никаких SQL-инъекций!)

> > > cur.выполнить ("вставить в тест (Нум данных) значения (%с, %S)", ... (100, "abc'Def"))

В вызове

cur.execute("INSERT INTO test (value_1,value_2) VALUES ('{value1}',{value2})".\
           format(value1=value_1,value2=value_2))

Вы сами интерполируете значения и просто передаете полученную строку методу cursor execute.

Простая интерполяция восприимчива к SQL-инъекции. Вам, вероятно, лучше использовать первую форму.

Вы всегда должны рассматривать "маленькие таблицы Бобби".

Прочитав некоторые документы и исходный код и протестировав это самостоятельно, я понял это правильно. Простой ответ: это чертовски небезопасно. Не только для psycopg2, но и для любого модуля БД (по крайней мере, для тех, которые я тестировал). Связывая это с psycopg2, использование (%s), (переменная,) позволяет psycopg2 автоматически экранировать эти переменные, чтобы предотвратить такой беспорядок.

Мой тест для выяснения небольшого беспорядка, который он может создать:

cur.execute("INSERT INTO test (value_1,value_2) VALUES ('{value1}','{value2}')".\
format(value1=value_1,value2='1); drop table test; --killer instinct'))

Вот и все, тестовая таблица adiós: - P

Да, Psycopg2 использует %s для всех типов, psycopg2 преобразует параметры в их строковое представление и использует его в запросе

INSERT INTO test (value_1,value_2) VALUES('test','100');

Иногда может потребоваться привести некоторые значения к типу apropriate.

 cur.execute("""INSERT INTO test (value_1,value_2) 
       VALUES (%s,%s::integer)""",
       (value_1,value_2))

Предложенный вами метод является очень плохой практикой, у вас есть SQL-инъекция для нескольких возможных значений value_1 и value_2. например:

 value_1="',0); rollback; drop table test ; --"