前后端加密(一):前端请求加密封装

本文共有4968个字,页面加载耗时0.001秒,关键词:

现在网站开发很多都用到前后端分离,保证API调用时数据的安全性便成了当务之急。
本文提供使用RAS非对称加密的方式传输数据。

1.保证API调用时数据的安全性的几种方式

  1. 使用HTTPS
  2. 使用数字签名确认,防止数据被篡改
  3. 身份确认机制,每次请求都要验证是否合法
  4. 对所有请求和响应的数据都进行加解密操作

2.加密思路介绍

本文着重对第4点进行介绍:对所有请求和响应的数据都进行加解密操作

实现思路

由上图可知,数据在网络上传输时,都是使用密文传输,即使被抓包,没有私钥也没办法获取到原始数据。对于用户和业务逻辑而言,加解密过程则是透明的。

3.前端加密封装

3.1.生成公钥、私钥

可以使用在线工具进行生成: 在线生成非对称加密公钥私钥对
也可以使用 openssl 进行生成
建议生成两套密钥对,服务器一套,前端一套
建议生成两套密钥对,服务器一套,前端一套
建议生成两套密钥对,服务器一套,前端一套

注意:密钥长度: 1024 bit
密钥格式:PKCS#8

3.2.创建加解密工具类

需要安装jsencrypt

npm i jsencrypt -S
/*** RSAUtil.js ***/

import JSEncrypt from 'jsencrypt'

/*** 换成你自己的生成的公钥(PUBLIC KEY) ***/
const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD9WVA/IMOrCb4SnO6zPuMfmQhM
KVSOL+N095MLLSG3f22MqasH1ZHSeAiaO92JRzdvufl0zAbhcZnUD2rmITryalwb
hSC2NnwaGcIujIONdFf11Gw31JIHHhMlbDK43tJdkdRY79I9KDF8m3tmkkOvqCJJ
4wjeEktuSs+sUwM9CQIDAQAB
-----END PUBLIC KEY-----`

/*** 换成你自己的生成的私钥(PRIVATE KEY) ***/
const privateKey = `-----BEGIN PRIVATE KEY-----
MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAP1ZUD8gw6sJvhKc
7rM+4x+ZCEwpVI4v43T3kwstIbd/bYypqwfVkdJ4CJo73YlHN2+5+XTMBuFxmdQP
auYhOvJqXBuFILY2fBoZwi6Mg410V/XUbDfUkgceEyVsMrje0l2R1Fjv0j0oMXyb
e2aSQ6+oIknjCN4SS25Kz6xTAz0JAgMBAAECgYEAu1lgzk4cZE9AD+OdYVAQBT3V
tPybWspvGgA67PjjBh9lk6+kmpaEz2+UbPn4SZwwkp6kqop2TCEF8Ju2IZhRTZpQ
wIcox+ZSQwXPiKAXtZi6L4P8DwNfr/l5e/EBPlMlwUlfavm0WFS/z/CcilrjbHqw
lVZOWC85JX4+ucTP2AECQQD+/86oySkhuerh9YaBe4fqnk/dPGuQFmIFeHSbSVCD
2T35sfXUxoSnX1KRAG4P4Y0D1ZvpEYbrXK3hDkygDa15AkEA/lfZHbVehG96ZRYx
oz5V6SUxrkXBnxdkDf1gjf1bZrMJM7ml/pE+67Dsrgm+1HXfi7iFtdOZFnHlZGiW
3pp4EQJBAIEiwOB/RuI6ifW2ZlCKY5FwbNeIMpy8iRVmI/9ECI9M4/LgqbMAectd
Ha4q/pHyUnx/n75PTvlAbRoNKMbhRlkCQQDfpyYfjqYPdOu+yjZZ4u2ut2spYOOy
3uG3v4/RK/HcrCCyYFSMNvKKVKi7HYy1zPUHKvpA+lGKwBrEIYhRNKnRAkEAmEDq
YrEL6DZeCLNHgYT9GZ3t87+dOGmonEjDBRrj4Z0HUok3tVV+0y3bKLkLr6fniqKh
mHTUs4tjYPRAhEkBzg==
-----END PRIVATE KEY-----`

const crypt = new JSEncrypt()
crypt.setPublicKey(publicKey)
crypt.setPrivateKey(privateKey)

function encrypt(data) {
    const res = crypt.encrypt(JSON.stringify(data))
    // 字符+和/分别替换成点 . 和下划线 _
    return res.replace(/\+/g, '.').replace(/\//g, '_')
}

function decrypt(encryptData) {
    // 将上面替换的规则还原
    encryptData = encryptData.replace(/\./g, '+').replace(/_/g, '/')
    return JSON.parse(crypt.decrypt(encryptData))
}

export default {encrypt, decrypt}

3.3.基于Axios封装request

需要安装axios

npm i axios -S
/*** requrst.js ***/
import axios from 'axios'
import RSAUtil from './RSAUtil'
// 创建axios实例
const service = axios.create({
    baseURL: 'YOUR_BASE_URL', // url = base url + request url
    timeout: 5000
})

// 请求拦截器,用来加密请求数据
service.interceptors.request.use(
    config => {
        if (typeof config.data !== 'undefined') {
            config.data = {
                data: RSAUtil.encrypt(JSON.stringify(config.data))
            }
        }
        if (typeof config.params !== 'undefined') {
            config.params = {
                params: RSAUtil.encrypt(JSON.stringify(config.params))
            }
        }
        return config
    },
    error => {
        // do something with request error
        console.log(error) // for debug
        return Promise.reject(error)
    }
)

// 响应拦截器,用来解密服务端的数据
service.interceptors.response.use(
    response => {
        // 解密后再返回
        response['rawData'] = response.data
        response['data'] = JSON.parse(RSAUtil.decrypt(response.data))
        if (response.rawData !== null && response.data === null) {
            return Promise.reject("私钥错误,解密失败")
        }
        return response
    },
    error => {
        console.log('err' + error)
        return Promise.reject(error)
    }
)

export default service

4.测试

测试数据:

原始数据:`{name: "zhangsan"}`
密文:`X3IhyCFhwdO5aA8TvZfgct8jKX_HE21gEy.ZBpJtvYPWKq2bGxtjs.LxQ8Usa.KJi9oo209zgv8p8qDRVmWR5tZZeTxvAp7qR_miGE.Wtx9rkEBU9TMmeK5mOcgIDtbz8Uc9qwnYLY4fWWhUhDNfzIeMuatImtAHVYhHTssss1M=`

4.1.GET请求测试

import service from "../utils/request";
const res = await service.request({
    url: 'https://getman.cn/mock/hsmus-top-ras-mock',
    method: 'GET',
    params: {
        name: 'zhangsan'
    }
})
console.log(res)

GET请求测试结果

4.1.POST请求测试

import service from "../utils/request";
const res = await service.request({
    url: 'https://getman.cn/mock/hsmus-top-ras-mock',
    method: 'POST',
    params: {
        name: 'zhangsan'
    }
})
console.log(res)

POST请求测试结果

扫码在手机查看