vue3-encapsulates AES (CryptoJS) front-end encryption and decryption communication

Project scenario:

To prevent data from being crawled, the parameters passed and received at the front and back ends need to be encrypted, using AES encryption. Mainly use the function methods in the CryptoJS library, encryption: CryptoJS.AES.encrypt(), decryption: CryptoJS.AES.decrypt().


Code

  1. Install the CryptoJS library:
npm install crypto-js
  1. Create a folder, @/utils/secret, introduce the CryptoJS library and encapsulate the encryption and decryption function methods:
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. Introduce the encryption and decryption method to encrypt the unified processing of requests encapsulated in Axios before the 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-ignore
      const {
    
     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. Unified processing before response to decrypt the 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. 获取到刷新token
          if (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);

final effect

Encrypted parameter transfer:
Insert image description here

Backend return parameter encryption:
Insert image description here
online encryption and decryption tool: https://www.mklab.cn/utils/aes

Insert image description here

Guess you like

Origin blog.csdn.net/fat_shady/article/details/129322195
Recommended