Oct1a

Vue网站数据传输加密

为了数据安全,防止被黑客模拟字段恶意发请求攻击,决定在前端,服务端,脚本上都对数据传输进行加解密

为了都能加解密,所需要的库也是要一样的,否则算法不一致就无法解密,目前 使用的是非对称密钥加密,库使用crypto

网站前端:

iv 偏移量使用当前时间戳进行截取前六位数,为了严谨是可以多截取几位,但不能太多,否则在59分到00分时,会出现偏移量不一致无法解密,然后再补齐至16位数

const crypto = require('crypto')
const iv = new Buffer(String(new Date().getTime()).slice(0, 6) + '0000000000') // 要16位才转buffer
const key = window.location.hostname

export function encryp(data) {
  if (!data || data.length <= 0) {
    return data
  }
  if (typeof data === 'object') {
    // 如果传入的data是json对象,先转义为json字符串
    try {
      data = JSON.stringify(data)
    } catch (error) {
      console.log('error:', error)
    }
  }
  const decodeKey = crypto.createHash('sha256').update(key, 'utf-8').digest()
  const cipher = crypto.createCipheriv('aes-256-cbc', decodeKey, iv)
  return cipher.update(data, 'utf8', 'base64') + cipher.final('base64')
}

export function decrypt(data) {
  const encodeKey = crypto.createHash('sha256').update(key, 'utf-8').digest()
  const cipher = crypto.createDecipheriv('aes-256-cbc', encodeKey, iv)
  return cipher.update(data, 'base64', 'utf8') + cipher.final('utf8')
}

工具库写完后,需要在全局发送请求与接收请求上对数据进行加解密

import { encryp, decrypt } from '@/utils/crypto'
service.interceptors.request.use(
  (config) => {
    if (store.getters.token) {
      // 头部增加token验证
      config.headers['X-Token'] = getToken()
    }
    if (config.data !== undefined || config.data) {
      // 设置请求头为 表单提交头
      config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
      // 设置提交数据为form表单格式
      const formData = new FormData()
      const encrypts = encryp(config.data)
      formData.append('p', encrypts) // 对请求参数数据进行加密
      config.data = formData
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

service.interceptors.response.use(
  (response) => {
    let res = response.data
    // 由于站内有些请求是第三方网站的,所以这边加了字段判断,
    // 也可以根据response.config的网站进行判断是否属于自身网站请求
    if (res.b) {
      // 对返回数据进行解密
      res = JSON.parse(decrypt(response.data.b))
    }
  },
  (error) => {
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

网站后端:

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。