在PL/pgSQL中使用关键字清理用户输入
这就是我创建搜索词的方法:在PL/pgSQL中使用关键字清理用户输入,sql,database,postgresql,plpgsql,dynamic-sql,Sql,Database,Postgresql,Plpgsql,Dynamic Sql,这就是我创建搜索词的方法: IF char_length(search_term) > 0 THEN order_by := 'ts_rank_cd(textsearchable_index_col, to_tsquery(''' || search_term || ':*''))+GREATEST(0,(-1*EXTRACT(epoch FROM age(last_edited)/86400))+60)/60 DESC'; search_term
IF char_length(search_term) > 0 THEN
order_by := 'ts_rank_cd(textsearchable_index_col, to_tsquery(''' || search_term || ':*''))+GREATEST(0,(-1*EXTRACT(epoch FROM age(last_edited)/86400))+60)/60 DESC';
search_term := 'to_tsquery(''' || search_term || ':*'') @@ textsearchable_index_col';
ELSE
search_term := 'true';
END IF;
我在使用PLPGSQL函数时遇到一些问题:
RETURN QUERY EXECUTE '
SELECT
*
FROM
articles
WHERE
$1 AND
' || publication_date_query || ' AND
primary_category LIKE ''' || category_filter || ''' AND
' || tags_query || ' AND
' || districts_query || ' AND
' || capability_query || ' AND
' || push_notification_query || ' AND
' || distance_query || ' AND
' || revision_by || ' AND
' || publication_priority_query || ' AND
' || status_query || ' AND
is_template = ' || only_templates || ' AND
status <> ''DELETED''
ORDER BY ' || order_by || ' LIMIT 500'
USING search_term;
END; $$;
返回查询执行'
挑选
*
从…起
文章
哪里
一元及
“| |出版|日期|查询| |”和
主|u类如“”||类|u过滤器| |“”,以及
“| |标记| | |”和
| |地区| | | |和
“| |能力| | |”和
“| |推送|通知|查询|”和
“| |距离| | |”和
| |修订| | |和
“| |发布|优先级|查询| |”和
“| |状态| | |”和
is|template='||仅|templates |和
状态“已删除”
按“| |按| |按|按|按|按|按|限500”订购
使用搜索词;
完(元);
返回错误:
和的参数必须是布尔类型,而不是字符64处的文本类型
与之相反:
RETURN QUERY EXECUTE '
SELECT
*
FROM
articles
WHERE
' || search_term || ' AND
' || publication_date_query || ' AND
primary_category LIKE ''' || category_filter || ''' AND
' || tags_query || ' AND
' || districts_query || ' AND
' || capability_query || ' AND
' || push_notification_query || ' AND
' || distance_query || ' AND
' || revision_by || ' AND
' || publication_priority_query || ' AND
' || status_query || ' AND
is_template = ' || only_templates || ' AND
status <> ''DELETED''
ORDER BY ' || order_by || ' LIMIT 500';
END; $$;
返回查询执行'
挑选
*
从…起
文章
哪里
“| |搜索| |”和
“| |出版|日期|查询| |”和
主|u类如“”||类|u过滤器| |“”,以及
“| |标记| | |”和
| |地区| | | |和
“| |能力| | |”和
“| |推送|通知|查询|”和
“| |距离| | |”和
| |修订| | |和
“| |发布|优先级|查询| |”和
“| |状态| | |”和
is|template='||仅|templates |和
状态“已删除”
按| |按| |按| |按|按|按| | |限制500 |订购|;
完(元);
。。。这很有效。我错过什么了吗?我的目标是清理我的用户输入。如果您的一些输入参数可以为NULL或空,并且在这种情况下应该忽略,那么您最好根据用户输入动态构建整个语句,并完全省略相应的
WHERE
/ORDER BY
子句
关键是在这个过程中正确、安全(优雅)地处理NULL和空字符串。对于初学者来说,search\u term'
是比char\u length(search\u term)>0更聪明的测试。见:
您需要对PL/pgSQL有一个坚定的理解,否则您可能会陷入困境。您案例的示例代码:
CREATE OR REPLACE FUNCTION my_func(
_search_term text = NULL -- default value NULL to allow short call
, _publication_date_query date = NULL
-- , more parameters
)
RETURNS SETOF articles AS
$func$
DECLARE
sql text;
sql_order text; -- defaults to NULL
BEGIN
sql := concat_ws(' AND '
,'SELECT * FROM articles WHERE status <> ''DELETED''' -- first WHERE clause is immutable
, CASE WHEN _search_term <> '' THEN '$1 @@ textsearchable_index_col' END -- ELSE NULL is implicit
, CASE WHEN _publication_date_query <> '' THEN 'publication_date > $2' END -- or similar ...
-- , more more parameters
);
IF search_term <> '' THEN -- note use of $1!
sql_order := 'ORDER BY ts_rank_cd(textsearchable_index_col, $1) + GREATEST(0,(-1*EXTRACT(epoch FROM age(last_edited)/86400))+60)/60 DESC';
END IF;
RETURN QUERY EXECUTE concat_ws(' ', sql, sql_order, 'LIMIT 500')
USING to_tsquery(_search_term || ':*') -- $1 -- prepare ts_query once here!
, _publication_date_query -- $2 -- order of params must match!
-- , more parameters
;
END
$func$ LANGUAGE plpgsql;
更多:
注意concat_ws()
的策略用法。见:
下面是一个相关的答案,有很多解释:
那么问题在于$1
什么是搜索词
?如果它类似于column\u a='some\u string'
,那么它将不适用于准备好的语句,因为这些语句不能用于动态SQL。search\u term
是用户输入的一个任意字符串值。那么有没有其他方法来清理我的用户输入?search\u term
不能只是一个任意字符串值。执行时,它必须是一个计算为布尔值的表达式,否则您的第二个代码片段也会出错。请显示一个和一些示例输入。不要将整个代码片段与大量不相关的噪声一起转储,而忽略了重要的部分。首先,这两种尝试都不利于清理用户输入。正在打开SQL注入漏洞。。。
SELECT * FROM my_func(_publication_date_query => '2016-01-01');