2015-04-03 97 views
2

我正在编写原始SQL查询以在我的节点后端中实现Postgres全文搜索。我已经浏览了official docs,其状态为:如何在Postgres /节点中正确地转义原始SQL查询(plainto_tsquery)

plainto_tsquery将未格式化的文本querytext转换为tsquery。与to_tsvector一样,文本被解析并标准化,然后在存活的单词之间插入(AND)布尔运算符。

,但我不是所有的不同的SQL注入技术,不知道确切足够熟悉是否下面会正确转义:

'SELECT * FROM "Products" WHERE "catalog_ts_vector" @@ plainto_tsquery(\'english\', ' + search_term + ')' 

用户将能够进入他们想要的任何search_term通过URI。

我是否需要进一步转义/操作,还是将此功能完全烘焙到plainto_tsquery()和其他Postgres保护措施中?

编辑

作为边注,我打算去掉最非字母数字字符(包括括号内)与.replace(/[^\w-_ .\&]|\(\)/g, ' ');这应该有很长的路要走,但是如果甚至有必要,我仍然很好奇。

回答

8

最有可能您将pg模块用作node.js的PostgreSQL客户端。在这种情况下,你不需要担心sql注入,pg可以阻止你。只是没有使用字符串concatination创建查询,使用参数化查询(或prepared statement):

var sql = 'SELECT * FROM "Products" WHERE "catalog_ts_vector" @@ plainto_tsquery(\'english\', $1)'; 
var params = [search_term]; 

client.query(sql, params, function(err, result) { 
    // handle error and result here 
}); 

也期待在pg维基Prepared Statment一部分和PostgreSQL PREPARE声明。

UPDsequelize什么 - 它使用pg模块默认,但你可以指定你dialectModulePath配置参数(见here)最好PG客户端。您也可以在sequelize中使用参数化查询。更好 - 你可以使用命名参数。所以,你的代码将是:

var sql = 'SELECT * FROM "Products" WHERE "catalog_ts_vector" @@ plainto_tsquery(\'english\', :search_term)'; 
var params = { search_term: search_term } 

sequelize.query(sql, Product, null, params).then(function(products) { 
    // handle your products here 
}) 

哪里Product是您sequelize产品型号。

+1

我没有直接使用'pg';使用'sequelize'代替。它看起来好像有一种方法可以转义值:'sequelize.getQueryInterface()。escape(search_term)''。如果您可以将其纳入您的答案,我很乐意将其标记为解决方案。 – tyler 2015-04-03 21:17:16

+0

@tyler更新了答案。 – alexpods 2015-04-03 21:37:17

+0

感谢您的更新。请注意,格式(params as'sequelize.query'的第4个选项)最近已被弃用:https://github.com/sequelize/sequelize/blob/master/changelog.md#backwards-compatibility-changes – tyler 2015-04-03 22:30:01