Express.js结合PostgreSQL通过URL查询数据库返回全部人员数据问题排查
问题原因
- 缺少查询参数合法性校验:若请求未携带
q查询参数、q为空字符串/空格时,没有拦截非法请求直接执行查询,若通配符逻辑处理不当会生成LIKE '%%'的匹配条件,命中所有非空的firstname字段,返回全表数据。 - LIKE查询逻辑不符合预期:当前SQL直接使用
LIKE $1未加通配符%,只能做精确匹配,无法实现模糊检索;若参数为空时拼接了通配符会直接匹配所有数据。 - 路由匹配顺序错误:如果项目中存在
GET /person的全量人员查询接口,且该接口的注册顺序在当前接口之前,请求会优先命中全量查询接口,直接返回全表数据。 - 返回结果格式错误:
pg库的pool.query返回的是封装后的查询对象,实际的业务数据存在于返回值的rows属性中,直接返回整个对象会携带多余字段,也容易掩盖查询逻辑的问题。
修复方案
- 新增参数校验逻辑,拦截空查询的非法请求,避免无意义的数据库查询
- 在SQL语句中拼接
%通配符,按照业务需求实现模糊匹配,通配符拼接放在SQL侧执行避免SQL注入风险 - 检查路由注册顺序,精准路由放在通用路由前,也可以给当前模糊查询接口设置独立路由如
/person/search避免路由冲突 - 接口返回数据只取结果对象中的
rows属性,返回实际的人员列表数据
修复后的代码如下:
exports.getPersonByName = async (req, res) => { const query = req.query.q // 校验查询参数合法性 if (!query || typeof query !== 'string' || query.trim() === '') { return res.status(400).json({ message: '查询参数q不能为空' }) } try { // '%' || $1 || '%' 为全模糊匹配,按需调整通配符位置即可 const result = await pool.query('SELECT * FROM person WHERE firstname LIKE \'%\' || $1 || \'%\'', [query.trim()]) // 只返回实际的人员数据 res.status(200).json(result.rows) } catch(error) { res.status(500).json({ message: error.message }) } }
注意:如果仅需要前缀匹配(如搜索
李仅返回姓李的用户),可以将通配符放在参数后侧,SQL改为LIKE $1 || \'%\';仅需要后缀匹配则把通配符放在参数前侧即可。
内容的提问来源于stack exchange,提问作者Mads Kristian Nylund
相关产品推荐
相关产品推荐

