有時候需要對項目的請求和返回值進行加密請求,因而筆者使用了sm4
,讀者也可以使用別的庫如md5
封裝加解密:
// ciphertext.js
const sm4 = require('sm-crypto').sm4
// 此爲密文key,非常重要
export const CIPHERTEXT = `wzdxcskwzdxcskwzdxcskwzdxcskwzdxcsk` //我真的想喫燒烤我真的想喫燒烤我真的想喫燒烤我真的想喫燒烤
/**
* 參考:
* https://github.com/JuneAndGreen/sm-crypto#sm4
*
* */
// 數據加密 用於axios請求攔截器
export const encryptSm4 = ( requestParams = '' )=>{
if (!requestParams) return
return sm4.encrypt(requestParams, CIPHERTEXT)
}
// 數據解密 用於axios相應攔截器
export const decryptSm4 = ( result = '' )=>{
if (!result) return
return sm4.decrypt(result, CIPHERTEXT)
}
響應/請求攔截中使用加解密方法,以下只寫要改動的,其餘的可以不變
// request.js
import axios from "axios";
import store from "../store";
import { encryptSm4, decryptSm4 } from "./ciphertext";
//生成axios實例
const service = axios.create({
// axios默認統一數據
timeout: 120000, //指定請求超時的毫秒數(0 表示無超時時間)
// baseURL:xxxx, //可能有不同類型的api地址,可以在這裏設置baseurl,後續中用以對比是否源於指定的url
// 如果要校驗請求類型,就需要先在這裏聲明`contenttype`
headers: {
"Content-Type": "application/json" // 設置默認json格式以規避在攔截器中拿不到 content-type問題
}
});
// 確認config配置項
const configCheck = (conf, type) => {
// 此處可根據需要自定義校驗
const isPost = conf.method.toUpperCase() === `POST`; // 是否post
// const jsonReg = /application\/json/; // 正則表達式匹配'application/json'
// const isJSON = jsonReg.test(conf.headers[`Content-Type`]) // 是否JSON
const isFromBaseURL = conf.baseURL.includes(process.env.VUE_APP_BASE_API); //是否基於baseurl
// console.log('isFromBaseURL :>> ', conf.baseURL, isFromBaseURL);
// console.log('process.env.VUE_APP_BASE_API :>> ', process.env.VUE_APP_BASE_API);
return {
send: [isFromBaseURL, isPost],
receive: [isFromBaseURL]
}[type].every(v => v);
};
// 請求攔截配置
/**
* 有以下方可進行加密:
* configCheck 爲true
* 明確`store`中`encryption`爲1 後端控制是否需要將請求/響應加密
service.interceptors.request.use(config=>{
...other code...
const isEncrypted = store.encryption === 1
if (isEncrypted && configCheck(config, `send`)) {
try {
const reqData = encryptSm4(JSON.stringify(config[`data`]));
config[`data`] = reqData ? reqData : config[`data`];
} catch (error) {
console.log("error :>> ", error);
}
}
...other code...
return config
})
// 響應攔截
service.interceptors.response.use(response=>{
let res = response.data; // 這裏故意用了`let` 因爲加密態下可能要改
// ---------------------- 此處爲解密校驗
const isEncrypted = store.encryption === 1
// 加密態下返回的只有一堆加密str,因而沒有`res.cdoe`屬性
if (!res.code && configCheck(response.config, `receive`) && isEncrypted) {
try {
// 解析加密數據
res = JSON.parse(decryptSm4(res));
if (typeof res === `string`) {
console.log(`--------------------`);
console.log("res :解析失敗返回值>> ", res);
console.log("失敗接口路徑爲 :>> ", response.config.url);
console.log("接口方法爲 :>> ", response.config.method);
console.log(`--------------------`);
}
// 解密後數據不一定是正常返回值,因而這裏做了簡單校驗
if (res.code && Number(res.code) !== 200) {
Message({
message: res.msg || "當前網絡繁忙,請稍後重試!",
type: "error",
duration: 3 * 1000
});
return Promise.reject(
new Error(res.msg || "當前網絡繁忙,請稍後重試")
);
}
} catch (error) {
console.log(`--------------------`);
console.log("error :>解析異常告警> ", error);
console.log("res :解析失敗返回值>> ", res);
console.log("失敗接口路徑爲 :>> ", response.config.url);
console.log("接口方法爲 :>> ", response.config.method);
console.log(`--------------------`);
}
}
// 👆----------------------------------- 此處爲解密校驗
// 接下來可以寫正常明文校驗,不表
return res
})
以上。