nodejs sequelize库防注入测试

本文探讨了在Node.js中使用Sequelize库时如何防止SQL注入,详细介绍了SQL注入的产生原因及解决办法。通过对比直接查询SQL语句和使用Sequelize接口的方式,阐述了参数绑定在防止注入中的重要作用,并提供了测试示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

  • 在nodejs中使用sequlize库来查询mysql数据库, 提供了常用的方法有两种:

    1. 直接查询sql语句: sequelize.query();
    2. 通过接口,如Project.findAll();
  • sequelize的第2种查询方法在实现上做了防注入处理, 但该方法使用并不是很灵活, 对于经常使用原生sql语句的人来说, 总有一种不适应, 感觉手脚被束缚; 而对于使用方法1, 则必须注意防sql注入;

这里我测试前面提到的两种查询方式如何做到初步的防sql注入功能;


sql注入

产生原因

下面的查询语句, 加入了用户输入的时间项: begin, end, 正常情况是:

begin = 20161101;
SELECT .. FROM tbl WHERE pdate>=20161101 AND ...;

而如果有人故意输入如下的参数, 则就会出现sql注入:

begin = '20161101 AND 1=1; -- hack';
SELECT .. FROM tbl WHERE pdate>=20161101 AND 1=1; -- hack ...;

解决办法

解决上面的办法, 通常有两种:
1. 对输入的参数进行转义, 因为sql注入通常需要'符号来闭合前面的', 这样如果位面在输入的参数中的'全部转义为\', 则查询时就不会出现中断(执行两条sql语句), 参看下面的例子;
2. 设置mysql只能一次执行一条sql语句;


测试

sequelize.query()Project.findAll()对比

先看代码

var tblName = 'tbl_test', begin = '20160923 AND 1=1;-- hack', end = 20160928;
var sqlQuery = `SELECT * FROM ${tblName} WHERE pdate>=${begin} AND pdate<=${end} GROUP BY pdate`;
Promise.resolve([
    // 第一条查询
    sequelize.query(sqlQuery),   
    // 第一二条查询
    Project.findAll({   
        attributes: { exclude:['id'] },
        where: {
            pdate: {
                $and:{
                    // 参数中加上了'来闭合前面的', 后面的1=1为注入语句
                    $gte: "20160923' AND 1=1;-- hack",   
                    $lte: end
                }   
            }
        }
    })
]).spread(function(sql1, sql2){

})
  • 上面第一个为sequelize.query()执行, 最终执行的查询语句为:
select * from tbl_test where padte>=20160923 and 1=1;-- hack and pdate<=....; 

结果出现注入, pdate<=..这一块的条件没有被执行;

  • 上面第二个查询为Project.findAll()执行, 最终执行的语句为:
select * from tbl_test where pdate>'20160923\' AND 1=1;-- hack' AND pdate<='...'.....; 

显然,这里参数里的20160923'引号没有起作用, 被转换为了`20160923\”,所以有效避免了注入, 制查询了符合要求的数据或空数据;


sequelize.query() + 参数绑定

下面通过sequelize.query()接口提供的参数绑定和查询方法指定来防止sql注入的发生.

  • 下面的查询语句解析为:
    select * from tbl_test where padte>='20160923 and 1=1;-- hack' and pdate<=....;
    字符串被直接替换,没有被注入;
  • 注意,这里的表名table不能通过bind的参数传进去, 因为这样在语句里会表达为字符串: …. from ‘tbl_test’ where …, 这样是错误的语句,所以上面用字符串模板传入,也可以硬编码进去;
var tblName = 'tbl_test', begin = '20160923 AND 1=1;-- hack', end = 20160928;
var sqlQuery = `SELECT * FROM ${tblName} WHERE pdate>=$begin AND pdate<=$end GROUP BY pdate`;
Promise.resolve([
    sequelize.query(sqlQuery,
        type: ymModel.sequelize.QueryTypes.SELECT,  // 指定sql为SELECT
        bind: { 
            begin: begin, 
            end: end 
        }
    ),
]).spread(function(sql1){

})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值