Могу ли я безопасно предотвратить SQL-инъекцию, используя строковые константы PostgreSQL, заключенные в доллары?
Я знаю, что лучше всего обрабатывать динамические запросы, если их генерировать на уровне приложения с параметризованным запросом, это не то, чтовопрос о.Вся бизнес-логика в хранимых процедурах.
У меня есть хранимая процедура, которая принимает параметры и генерирует запрос, выполняет его, форматирует результаты и возвращает его в виде фрагмента текста.Этой функции передаются имя таблицы, имена столбцов и параметры WHERE.Параметры WHERE, передаваемые в функцию, взяты из введенных пользователем данных в базе данных.Я хотел бы убедиться, что строки очищены, поэтому построенный запрос является безопасным.
Используя строковые константы в кавычках PostgreSQLs, я должен быть в состоянии безопасно санировать весь ввод строки, кроме '$$',Однако, если я заменю строку на «$», чтобы избежать ее, я смогу выполнить безопасное сравнение строк.
Хранимая процедура:
function_name(tablename text, colnames text[], whereparam text)
--Build dynamic query...
Вызов функции:
SELECT
function_name('tablename', ARRAY['col1', 'col2', 'col3'], 'AND replace(col1, ''$'', ''/$'') = $$' || replace(alt_string_col, '$', '/$') || '$$ ')
FROM alttable
WHERE alt_id = 123;
Сгенерированный запрос:
SELECT col1, col2, col3 FROM tablename WHERE 1=1 AND replace(col1, '$', '/$') = $$un/safe'user /$/$ data;$$
Поскольку я экранирую поле col1, прежде чем сравнивать его с экранированными пользовательскими данными, даже если пользователь вводит, "un / safe'user"$$ data; "в поле alt_string_col двойной знак доллара не прерывает запрос и сравнение проходит.
Это безопасный способ экранирования строк в хранимой процедуре PostgreSQL?
Edit1
Спасибо Эрвину Брандштеттеру.Используя предложение USING
для EXECUTE
, я собирался создать функцию, которая может быть вызвана следующим образом:
SELECT function_name(
'tablename',
ARRAY['col1', 'col2', 'col3'],
ARRAY[' AND col1 = $1 ', ' OR col2 = $5 '],
quote_literal(alt_string_col)::text, --Text 1-4
NULL::text,
NULL::text,
NULL::text,
alt_active_col::boolean, --Bool 1-4
NULL::boolean,
NULL::boolean,
NULL::boolean,
NULL::integer, --Int 1-4
NULL::integer,
NULL::integer,
NULL::integer
)
FROM alttable
WHERE alt_id = 123;
Это дает некоторую гибкость предложениям WHERE, которые могут быть переданы.
Внутри хранимой процедуры у меня есть что-то подобное для оператора EXECUTE
.
FOR results IN EXECUTE(builtquery) USING
textParm1,
textParm2,
textParm3,
textParm4,
boolParm1,
boolParm2,
boolParm3,
boolParm4,
intParm1,
intParm2,
intParm3,
intParm4
LOOP
-- Do some stuff
END LOOP;