最近在学习后端nodejs项目搭建,在做用户登录功能是遇到了SQL注入问题,小记一下。
背景:使用nodejs操作mysql
登录逻辑
在获取到前端传过来的账号和密码的时候,我们需要拿到用户的账号信息去数据库匹配,一般的查询sql语句是:
`select * from user where username = '${username}' and password = '${password}';`
如果查到数据库中有对应的账号和密码就验证通过,继续登录逻辑。
此时就会有个问题,我们的username 是前端输入框的值,例如:
正常输入是没有问题的,此时执行的sql语句是:
`select * from user where username = 'zhangsan' and password = '123456';`
假如有不怀好意的的人输入的账号带有特殊字符,他输入的账号是 zhnagsan'-- ,进行登录操作时,我们后台数据库接收到的sql语句就变成了
`select * from user where username = 'zhnagsan'-- ' and password = '123456';`
用可视化工具看就是
可以注意到用户名后面的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注入
};`
所以在登录逻辑中处理用户的账号和密码时,先给数据进行转义一下
`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注入办法,了解一下,加深理解。