天天看點

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
}
           

繼續閱讀