天天看点

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

一、安全

  1. 对于安全,如下所示:
  • sql

    注入:窃取数据库内容
  • XSS

    攻击:窃取前端的

    cookie

    内容
  • 密码加密:保障用户信息安全
  • server

    端攻击方式非常多,预防手段也非常多
  • nodejs

    可以通过

    web server

    层面预防
  • 有些攻击需要硬件和服务来支持,需要

    OP

    支持,如

    DDOS

二、sql 注入

  1. sql

    注入,如下所示:
  • 最原始、最简单的攻击,从有了

    web2.0

    就有了

    sql

    注入攻击
  • 攻击方式:输入一个

    sql

    片段,最终拼接成一段攻击代码
  • 预防措施:使用

    MySQL

    escape

    函数处理输入内容即可
  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
}
           

继续阅读