如何使用AES加解密提高项目安全性

安装依赖并引入

yarn add crypto-es jsencrypt
CryptoES.mode: ECBCBC(需要多加一个偏移量iv)

import CryptoES from 'crypto-es';
import JSEncrypt from 'jsencrypt';

注: 引入后报错 Can't resolve './JSEncrypt'

解决方法:

  • 原始webpack配置修改
// webpack配置 module.rules添加
{
    test: /\.m?js/,
    resolve: {
        fullySpecified: false
    }
}
  • 使用 config-overrides.js修改webpack配置
const path = require('path');
const { override, addWebpackModuleRule } = require('customize-cra');

module.exports = override(
    addWebpackModuleRule(
        {
            test: /\.m?js/,
            resolve: {
                fullySpecified: false
            }
        }
    ),
)

一、非对称加解密

前后端用公钥加密,AES 解密

加密

  • REACT_APP_SSOPUBLICKEY 公钥
  • 存储在环境变量中(.env)
// 与后端约定共同使用公钥加密
const encryptor = new JSEncrypt();
encryptor.setPublicKey(process.env.REACT_APP_SSOPUBLICKEY ?? '');

// 随机数的方法
const aesKey = CryptoES.lib.WordArray.random(128 / 8).toString()
const aesIv = CryptoES.lib.WordArray.random(64 / 8).toString()

// 与后端约定前16位作为iv偏移量
const aesKeyVaue = encryptor.encrypt(aesIv + aesKey) || ''

.env文件

REACT_APP_SSOPUBLICKEY=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4ZPpIWdiMDcj8ELgtvPlxaEpKw7iHrqDhHrx92QMil1ZO/XvCJK1R1G4Tp5YV8hX9mp0qac8I+LNJ82zZMBpTdXEUlmlqtCuRMq9u1UcYN+hAlf6UL1LhKRXlEx5+EXBc4sgjUJUg8uYSqwIA8AfmbVU7bwODfwsxwFM2JVHbuwIDAQAB

解密

  • CryptoES.AES.decrypt 两个参数(需要解密的对象、解密的key)
api.loginGetAccessInfo({
    key: aesKeyVaue,
    token: encryptor.encrypt(token ?? '') || ''
}).then((res: Respobject, { isOk }) => {
    if (isOk) {
        const decrypt = CryptoES.AES.decrypt(res.data, CryptoES.enc.Utf8.parse(aesKey),
            {
                iv: CryptoES.enc.Utf8.parse(aesIv),
                mode: CryptoES.mode.CBC,
                padding: CryptoES.pad.Pkcs7
            });
        // 获取解密后的data对象
        const data = JSON.parse(CryptoES.enc.Utf8.stringify(decrypt).toString());
        this.onUserInfoLoaded(data)
        // 存储 key iv
        localStorage.setItem('jst-aesKey', aesKey)
        localStorage.setItem('jst-aesIv', aesIv)
    } else {
        localStorage.clear()
        this.setState({ oauthSuccess: false })
    }
}).catch(() => {
    localStorage.clear()
    this.initUserInfo()
})

请求接口
如何使用AES加解密提高项目安全性_第1张图片

详细代码如下
如何使用AES加解密提高项目安全性_第2张图片

二、对称加解密

  • 前端用 aesKey 加解密
  • 对请求参数request加密、对返回的response 解密

拦截器中统一加解密

  • 对请求的接口参数body加密 排除登录的公钥加密
  • 正常接口返回responseData,报错直接返回code msg信息
this.axiosInstance
.request({
    url: path,
    method: req.method as any,
    data: this.handleRequest(path, req),
    headers: jstToken ? { ...headers, token: jstToken } : headers,
    responseType: 'json'
})
handleRequest = (path: string, req: SwaRequest<RequestOptions>) => {
    if (path.indexOf('/login/getAccessInfo') !== -1) {
        return req.body || {}
    }
    console.log('req==', req)
    console.log('enReq==', encrypt(req.body))
    return encrypt(req.body)
}

用存储的key iv加密加密

function encrypt(params: any) {
    const aesKey = localStorage.getItem('jst-aesKey') ?? ''
    const aesIv = localStorage.getItem('jst-aesIv') ?? ''
    const requestData = CryptoES.AES.encrypt(
        JSON.stringify(params),
        CryptoES.enc.Utf8.parse(aesKey),
        {
            iv: CryptoES.enc.Utf8.parse(aesIv),
            mode: CryptoES.mode.CBC,
            padding: CryptoES.pad.Pkcs7,
        }
    ).toString();
    return { requestData };
}

用存储的key iv加密解密

function decrypt(response: string) {
    console.log('加密res==', response)
    const aesKey = localStorage.getItem('jst-aesKey') ?? ''
    const aesIv = localStorage.getItem('jst-aesIv') ?? ''
    let data: string = ''
    const result = CryptoES.AES.decrypt(
        response,
        CryptoES.enc.Utf8.parse(aesKey),
        {
            iv: CryptoES.enc.Utf8.parse(aesIv),
            mode: CryptoES.mode.CBC,
            padding: CryptoES.pad.Pkcs7,
        }
    ).toString(CryptoES.enc.Utf8);
    for (let i = 0; i < result.length; i++) {
        if (result.charCodeAt(i) !== 0) {
            data += `${result[i]}`
        }
    }
    console.log('解密res==', JSON.parse(data))
    return JSON.parse(data);
}

你可能感兴趣的:(前端开发,网络请求,react.js,javascript,前端)