import axios from 'axios'
|
import apiConfig from './baseurl'
|
import store from '@/store' // 导入 Vuex store
|
import CryptoJS from 'crypto-js';
|
|
import {
|
Message
|
} from 'element-ui'
|
|
const service = axios.create({
|
baseURL: apiConfig.baseURL,
|
withCredentials: false, // 当跨域请求时发送cookie
|
timeout: 60000, // request timeout
|
})
|
// 对 POST 请求参数进行排序
|
const sortPostParams = (params) => {
|
const keys = Object.keys(params);
|
|
keys.sort((a, b) => {
|
for (let i = 0; i < Math.min(a.length, b.length); i++) {
|
const asciiA = a.charCodeAt(i);
|
const asciiB = b.charCodeAt(i);
|
|
if (asciiA !== asciiB) {
|
return asciiA - asciiB;
|
}
|
}
|
|
// 如果两个字符串长度不同,则较短的字符串排在前面
|
return a.length - b.length;
|
});
|
|
const sortedParams = {};
|
keys.forEach(key => {
|
sortedParams[key] = params[key];
|
});
|
|
return sortedParams;
|
}
|
//去除对象中空值的属性
|
const removeEmptyProperties = (obj) => {
|
return Object.fromEntries(Object.entries(obj).filter(([key, value]) => value !== undefined && value !== null && value !== '' && (Array.isArray(value) ? value.length > 0 : true)));
|
};
|
// 将对象转换为字符串用&拼接
|
const objToString = (obj) => {
|
// 使用 Object.keys() 获取对象的 key 数组
|
const keys = Object.keys(obj);
|
|
// 使用 Array.prototype.map() 将每个 key-value 对转化为字符串
|
const strArray = keys.map(key => {
|
|
const value = obj[key];
|
if (Array.isArray(value) || typeof value === 'object' && value !== null) {
|
return '';
|
} else {
|
return `${key}=${value}`;
|
}
|
});
|
|
// 使用 Array.prototype.filter() 过滤掉空字符串
|
const filteredStrArray = strArray.filter(str => str !== '');
|
|
// 使用 Array.prototype.join() 将字符串数组拼接成一个字符串
|
const str = filteredStrArray.join('&');
|
return str;
|
}
|
// 生成随机字符串
|
const generateRandomString = (length) => {
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
const str = [];
|
for (let i = 0; i < length; i++) {
|
const randomIndex = Math.floor(Math.random() * chars.length);
|
str.push(chars[randomIndex]);
|
}
|
return str.join('');
|
}
|
// 对字符串进行 HMAC-SHA1 加密
|
const encryptWithHMACSHA1 = (message, secret) => {
|
return CryptoJS.HmacSHA1(message, secret).toString(CryptoJS.enc.Base64);
|
};
|
|
// 请求拦截
|
service.interceptors.request.use(
|
config => {
|
const o = config
|
let { data, method } = o
|
const Authorization = localStorage.getItem('token') || ''
|
if (method == 'post') {
|
let copyData = JSON.parse(JSON.stringify(data))
|
// 对 POST 请求参数进行处理
|
let sortData = sortPostParams(copyData)
|
sortData = removeEmptyProperties(sortData)
|
// 将处理后的 POST 请求参数转换为字符串
|
let strData = objToString(sortData)
|
// 生成随机字符串 用作加密秘钥
|
let nonce_str = generateRandomString(16)
|
// 对字符串进行 HMAC-SHA1 加密 并转化为 Base64
|
|
let sign = encryptWithHMACSHA1(strData, nonce_str)
|
o.headers = {
|
...o.headers,
|
timestamp: new Date().getTime(),
|
sign,
|
nonce_str,
|
Authorization,
|
client: localStorage.getItem('client')
|
}
|
} else {
|
o.headers = {
|
timestamp: new Date().getTime(),
|
...config.headers,
|
Authorization,
|
client: localStorage.getItem('client')
|
}
|
}
|
return { ...o };
|
},
|
error => {
|
return Promise.reject(error)
|
}
|
)
|
|
// 响应拦截
|
service.interceptors.response.use(
|
response => {
|
if (!response) {
|
return
|
}
|
const res = response;
|
if (res.data.code == 200) {
|
if (!res.data.data) {
|
return Promise.resolve({})
|
}
|
return Promise.resolve(res.data.data)
|
} else {
|
if (res.data.code == 103 || res.data.code == 401) {
|
Message({
|
message: res.data.msg || '登录已过期,请重新登录',
|
type: 'warning',
|
duration: 2000
|
})
|
store.commit('clearToken')
|
window.location.replace(`/`);
|
return Promise.reject(res.data.data)
|
}
|
Message({
|
message: res.data.msg || '服务器错误',
|
type: 'error',
|
duration: 4000
|
})
|
return Promise.reject(res.data.data)
|
}
|
},
|
error => {
|
Message({
|
message: error.message,
|
type: 'error',
|
duration: 5000
|
})
|
return Promise.reject(error)
|
}
|
)
|
|
export default service
|