如何理解SQL注入及如何防止防止SQL注入——node.js

212 阅读2分钟

最近在学习后端nodejs项目搭建,在做用户登录功能是遇到了SQL注入问题,小记一下。

背景:使用nodejs操作mysql

登录逻辑

在获取到前端传过来的账号和密码的时候,我们需要拿到用户的账号信息去数据库匹配,一般的查询sql语句是:

`select * from user where username = '${username}' and password = '${password}';`

如果查到数据库中有对应的账号和密码就验证通过,继续登录逻辑。

此时就会有个问题,我们的username 是前端输入框的值,例如:

image.png

正常输入是没有问题的,此时执行的sql语句是:

 `select * from user where username = 'zhangsan' and password = '123456';`

假如有不怀好意的的人输入的账号带有特殊字符,他输入的账号是 zhnagsan'-- ,进行登录操作时,我们后台数据库接收到的sql语句就变成了

`select * from user where username = 'zhnagsan'-- ' and password = '123456';`

用可视化工具看就是

image.png

可以注意到用户名后面的sql语句变成了灰色。因为 --+空格 在sql中是注释的意思,相当于后面的语句没有执行了。 所以如果有人知道了你的用户名,就可以用这个方式去登录,直接绕过了密码校验,很危险。这个操作就是sql注入

  • 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。是最原始、最简单的攻击,从有了web2.0就有了sql注入攻击

为了防止有人恶意操作,我们要解决一下这个问题。我们知道mysql提供了转义特殊字符的功能escape

`let mysql  = require("mysql")

const connection = mysql.createConnection({
  host:"lcoalhost",
  user:"me",
  password:"pass",
  database:"mydb"
})
// connection.connect()

const exc = (sql)=>{
  return new Promise((resolve,reject)=>{
    connection.query(sql,(err,result)=>{
      if(err){
        reject(err)
      }else{
        resolve(result)
      }
    })
  })
}

module.exports = {
  exc,
  escape:mysql.escape   //mysql去除特殊字符的方法,防止SQL注入
};`



所以在登录逻辑中处理用户的账号和密码时,先给数据进行转义一下

image.png

`const {exc , escape} = require("../db/mysql")
async function getUser({username,password}){
  // 转义字符防止sql注入
  username =  escape(username)
  password = escape(password)
  //escape 会自动加双引号,所以不用再加
  // let sql = `select * from user where username = '${username}' and password = '${password}';`
  let sql = `select * from user where username = ${username} and password = ${password};`
  let result =  await exc(sql)
  return result
}`

这样数据库收到的sql语句就是:

`select * from user where username = 'zhnagsan \'-- ' and password = '123456';`

这样再执行时就不会出现问题了。

  • 所以为了预防万一,我们需要把能拼接成sql语句的变量都要用escape方法转义一下

这最简单的sql注入办法,了解一下,加深理解。