node JS 中安全和防范之 sql 注入、XSS攻击 和 密码加密

一、安全

  1. 对于安全,如下所示:
  • sql 注入:窃取数据库内容
  • XSS 攻击:窃取前端的 cookie 内容
  • 密码加密:保障用户信息安全
  • server 端攻击方式非常多,预防手段也非常多
  • nodejs 可以通过 web server 层面预防
  • 有些攻击需要硬件和服务来支持,需要 OP 支持,如 DDOS

二、sql 注入

  1. sql 注入,如下所示:
  • 最原始、最简单的攻击,从有了 web2.0 就有了 sql 注入攻击
  • 攻击方式:输入一个 sql 片段,最终拼接成一段攻击代码
  • 预防措施:使用 MySQLescape 函数处理输入内容即可
  1. sql 注入在 nodeJS 项目中的应用,如下所示:
  • db.js,代码如下所示:
const env = process.env.NODE_ENV // 环境参数

// 配置
let MYSQL_CONF
let REDIS_CONF

if (env === 'dev') {
    
    
  // mysql
  MYSQL_CONF = {
    
    
    host: 'localhost',
    user: 'root',
    password: '123456',
    port: '3306',
    database: 'nodeblog'
  }

  // redis
  REDIS_CONF = {
    
    
    port: 6379,
    host: '127.0.0.1'
  }
}

if (env === 'product') {
    
    
  // mysql
  MYSQL_CONF = {
    
    
    host: 'localhost',
    user: 'root',
    password: '123456',
    port: '3306',
    database: 'nodeblog'
  }

  // redis
  REDIS_CONF = {
    
    
    port: 6379,
    host: '127.0.0.1'
  }
}

module.exports = {
    
    
  MYSQL_CONF,
  REDIS_CONF
}
  • mysql.js,代码如下所示:
const mysql = require('mysql')
const {
    
     MYSQL_CONF } = require('../config/db')

// 创建连接对象
const con = mysql.createConnection(MYSQL_CONF)

// 开始连接
con.connect()

// 统一执行的 sql 的函数
function exec (sql) {
    
    
  // 返回 promise 对象
  const promise = new Promise((resolve, reject) => {
    
    
    con.query(sql, (err, result) => {
    
    
      if (err) {
    
    
        // console.error(err)
        reject(err)
        return
      }
      // console.log(result)
      resolve(result)
    })
  })

  return promise
  
}

module.exports = {
    
    
  exec,
  escape: mysql.escape
}
  • user.js,代码如下所示:
const {
    
     exec, escape } = require('../db/mysql')

const login = (username, password) => {
    
    

  username = escape(username)
  password = escape(password)

  const sql = `select username, realname from users where username=${
      
      username} and password=${
      
      password};`
  
  return exec(sql).then(rows => {
    
    
    return rows[0] || {
    
    }
  })
}

module.exports = {
    
    
  login
}

三、XSS 攻击

  1. XSS 攻击,如下所示:
  • 攻击方式:在页面展示内容中掺杂 js 代码,以获取网页信息
  • 预防措施:转换生成 js 的特殊字符
  1. XSS 攻击在 nodeJS 项目的应用,如下所示:
  • 通过 npm i xss --save 命令下载 xss 模块
  • blog.js 中,代码如下所示:
const xss = require('xss')
const title = xss(blogData.title)

  • 完整 blog.js,代码如下所示:
// controller 只关心数据
const {
    
     exec } = require('../db/mysql')
const xss = require('xss')

const getList = (author, keyword) => {
    
    
  // 先返回假数据,格式是正确的
  let sql = `select * from blogs where 1=1 `
  if (author) {
    
    
    sql += `and author='${
      
      author}' `
  }
  if (keyword) {
    
    
    sql += `and title like '%${
      
      keyword}%' `
  }
  sql += `order by createtime desc;`

  // 返回 promise
  return exec(sql)
}


const getDetail = (id) => {
    
    
  // 先返回的数据
  const sql = `select * from blogs where id='${
      
      id}'`
  return exec(sql).then(rows => {
    
    
    return rows[0]
  })
}


const newBlog = (blogData = {
    
    }) => {
    
    
  // blogData 是一个博客对象,包含 title、content 属性
  // console.log('newBlog blogData...', blogData)

  const title = xss(blogData.title)
  const content = xss(blogData.content)
  const author = blogData.author
  const createtime = Date.now()

  const sql = `insert into blogs (title, content, createtime, author)
              values ('${
      
      title}', '${
      
      content}', ${
      
      createtime}, '${
      
      author}');`
  
  return exec(sql).then(insertData => {
    
    
    console.log('insertData is ', insertData)
    return {
    
    
      id: insertData.insertId
    }
  })

}


const updateBlog = (id, blogData = {
    
    }) => {
    
    
  // id 就是要更新博客的 id
  // blogData 是一个博客对象,包含 title、content 属性
  
  const title = xss(blogData.title)
  const content = xss(blogData.content)

  const sql = `update blogs set title='${
      
      title}', content='${
      
      content}' where id=${
      
      id}`

  return exec(sql).then(updateData => {
    
    
    console.log('updateData is', updateData)
    if (updateData.affectedRows > 0) {
    
    
      return true
    }
    return false
  })
}


const deleteBlog = (id, author) => {
    
    
  // id 就是要更新博客的 id
  const sql = `delete from blogs where id=${
      
      id} and author='${
      
      author}';`

  return exec(sql).then(delData => {
    
    
    if (delData.affectedRows > 0) {
    
    
      return true
    }
    return false
  })
}


module.exports = {
    
    
  getList,
  getDetail,
  newBlog,
  updateBlog,
  deleteBlog
}

四、密码加密

  1. 密码加密,如下所示:
  • 万一数据库被用户攻破,最不该泄露的就是用户信息
  • 攻击方式:获取用户名和密码,再去尝试登陆其他系统
  • 预防措施:将密码加密,即便拿到密码也不知道明文
  1. 密码加密在 nodeJS 项目中的应用,如下所示:
  • cryp.js,代码如下所示:
const crypto = require('crypto')

// 密钥
const SECRET_KEY = 'Wzs_sd274#'

// md5 加密
function md5(content) {
    
    
  let md5 = crypto.createHash('md5')
  return md5.update(content).digest('hex')
}

// 加密函数
function genPassword(password) {
    
    
  const str = `password=${
      
      password}&key=${
      
      SECRET_KEY}`
  return md5(str)
}

// const result = genPassword('123')
// console.log(result)

module.exports = {
    
    
  genPassword
}
  • user.js,代码如下所示:
const {
    
     exec, escape } = require('../db/mysql')
const {
    
     genPassword } = require('../utils/cryp')

const login = (username, password) => {
    
    
  // 先使用假数据
  // if (username === 'zhangsan' && password === '123') {
    
    
  //   return true
  // }
  // return false

  username = escape(username)
  
  // 生成加密密码
  password = genPassword(password)
  password = escape(password)

  const sql = `select username, realname from users where username=${
      
      username} and password=${
      
      password};`
  
  return exec(sql).then(rows => {
    
    
    return rows[0] || {
    
    }
  })
}

module.exports = {
    
    
  login
}

猜你喜欢

转载自blog.csdn.net/weixin_42614080/article/details/111055966