项目场景:

防止数据被爬取,前后端传参接收参数需要加密处理,使用AES加密。主要使用CryptoJS库中的函数方法,加密:CryptoJS.AES.encrypt(), 解密:CryptoJS.AES.decrypt()。


代码实现

  1. 安装CryptoJS库:
npm install crypto-js
  1. 创建文件夹,@/utils/secret,引入CryptoJS库并封装加密解密函数方法:
import CryptoJS from 'crypto-js/crypto-js';const key = CryptoJS.enc.Utf8.parse('123321'); // 密钥 后端提供const iv = CryptoJS.enc.Utf8.parse(''); // 偏移量/** * AES加密 :字符串 key iv返回base64 */export function Encrypt(word) {const srcs = CryptoJS.enc.Utf8.parse(word);const encrypted = CryptoJS.AES.encrypt(srcs, key, {iv: iv,mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7,});return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);}/** * AES 解密 :字符串 key iv返回base64 **/export function Decrypt(word) {const base64 = CryptoJS.enc.Base64.parse(word);const src = CryptoJS.enc.Base64.stringify(base64);const decrypt = CryptoJS.AES.decrypt(src, key, {iv: iv,mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7,});return CryptoJS.enc.Utf8.stringify(decrypt);}
  1. 引入加密解密方法,对axios中封装的request 请求前的统一处理做加密:
// 引入import { Encrypt, Decrypt } from '/@/utils/secret';this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {// If cancel repeat request is turned on, then cancel repeat request is prohibited// @ts-ignoreconst { ignoreCancelToken } = config.requestOptions;const ignoreCancel =ignoreCancelToken !== undefined? ignoreCancelToken: this.options.requestOptions?.ignoreCancelToken;!ignoreCancel && axiosCanceler.addPending(config);if (requestInterceptors && isFunction(requestInterceptors)) {config = requestInterceptors(config, this.options);} // 关键代码: // JSON加密,formData不加密(对需要处理的数据格式做判断) if (Object.prototype.toString.call(config.data) != '[object FormData]') { config.data = { encryptedData: Encrypt(JSON.stringify(config.data)) }; // 加密传参,后端要求的传参:encryptedData:加密参数 }return config;}, undefined);
  1. response 响应前的统一处理做解密:
this.axiosInstance.interceptors.response.use(async (res: AxiosResponse<any>) => {// 关键代码:// 导出时数据格式为blob不解密(对需要处理的数据格式做判断)if (Object.prototype.toString.call(res.data) != '[object Blob]') {res.data = JSON.parse(Decrypt(res.data)); // 解密返回参数}const config = res.config;if (res.data.code === 401) {// 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了if (!isRefreshToken) {isRefreshToken = true;// 1. 获取到刷新tokenif (getRefreshToken()) {// 2. 进行刷新访问令牌try {const refreshTokenRes = await this.refreshToken();// 2.1 刷新成功,则回放队列的请求 + 当前请求setToken('Bearer ' + refreshTokenRes.data.data.accessToken);(config as Recordable).headers.Authorization = getToken();requestList.forEach((cb: any) => {cb();});requestList = [];return new Promise((resolve) => {resolve(this.axiosInstance(config));});// res = await Promise.all([this.axiosInstance(config)])[0]} catch (e) {requestList.forEach((cb: any) => {cb();});} finally {requestList = [];isRefreshToken = false;}}} else {// 添加到队列,等待刷新获取到新的令牌return new Promise((resolve) => {requestList.push(() => {(config as Recordable).headers.Authorization = getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改resolve(this.axiosInstance(config));});});}}res && axiosCanceler.removePending(res.config);if (responseInterceptors && isFunction(responseInterceptors)) {res = responseInterceptors(res);}return res;}, undefined);

最终效果

加密传参:

后端返回参数加密:

在线加密解密工具:https://www.mklab.cn/utils/aes