前后端数据传输加解密+请求重发
⽬的
确保前后端传输数据的安全性,避免明⽂显⽰,避免数据被篡改
⽅案⼀:
aes、rsa配合加密⽅案:
1. 对称加密⽣成密钥A(aes key)
2. ⽤密钥A对数据进⾏对称加密,⽣成数据的密⽂a
3. 使⽤服务器下发的⾮对称加密的公钥,对对称加密密钥A进⾏加密,⽣成密钥的密⽂b
4. 和数据的密⽂a、⽣成密钥的密⽂b传递给服务端
aes对称加密,利⽤其加解密速度快的特点,对报⽂整体参数进⾏加解密;然后利⽤rsa的加密难破解的特点,对aes key进⾏加解密⽅案⼆:
相对⽐较更安全的⽅案
公钥加密、私钥解密、私钥签名、公钥验签。
⽅案⼀具体实现
前端
1、aes加密采⽤Crypto.js插件
封装crypro.js
3、请求加解密封装,以及重发逻辑处理
/**
* 封装axios
* aes + rsa
* 1、请求前参数加密
* VUE_APP_RUNTIME
* ⽣产环境 prod: 加密
* ⽣产测试环境 prod-test: 明⽂传输,便于查看参数
* 开发环境:明⽂传输,便于查看参数
* 2、获取响应数据,解密处理,判断 res.headers.keycipher 是否需要解密
* 密⽂:前端获取⼀律需要解密转 json
*/
import { Message } from 'element-ui';
import axios from 'axios'
import moment from "moment";
import { isObject, isString, getItem } from './utils';
import { aesKey, inUseMockdata } from "./config";
import { aesEncrypt, aesDecrypt } from './crypto';
error parse newimport { rsaEncrypt, rsaDecrypt } from './jsencrypt';
axios.defaults.headers.post["Content-Type"] = "application/json; charset=UTF-8"
// 1. 创建新的axios实例,
const instance = ate({
baseURL: !inUseMockdata ? v.VUE_APP_BASEURL + v.VUE_APP_PREURL : '',
// `withCredentials`指⽰是否跨站点访问控制请求
withCredentials: true,
// "responseType"表⽰服务器将响应的数据类型
// 包括 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
responseType: 'json',
// headers`是要发送的⾃定义 headers
headers: {
// 'X-Requested-With': 'XMLHttpRequest',
'Cache-Control': 'no-store' // IE 禁⽤缓存 // 'no-cache'
},
// 超时时间单位是ms,这⾥设置了10s的超时时间
timeout: 10 * 1000,
transformRequest: [
function (data, headers) {
// 这⾥没有对 Form-Data 格式的报⽂处理
if (isObject(data)) {
// ⼀、请求参数加密
if (v.VUE_APP_RUNTIME === 'prod') {
data = JSON.stringify(data)
headers["keyCipher"] = rsaEncrypt(aesKey) // 传输 aes key 密⽂
data = aesEncrypt(data) // 加密请求参数
}
return data
}
return data
}
],
transformResponse: [
function (data, headers) {
if (isString(data)) {
try {
// 先对 axios 返回的源数据处理
data = JSON.parse(data)
/**
* ⼆、获取响应数据之后解密
* 判断 headers.keycipher 是否需要解密 (后端在接⼝报错的情况下,直接返回的是明⽂,不对错误信息加密) * 1、rsa 解密后端⽣成的 aes key
* 2、aes 解密返参密⽂
*/
const { keycipher = '' } = headers || {}
if (keycipher) {
// 解密
const resAesKey = rsaDecrypt(keycipher)
const dataStr = aesDecrypt(data, resAesKey) || '{}'
const dataStr = aesDecrypt(data, resAesKey) || '{}'
data = JSON.parse(dataStr)
}
console.log("res data ====", data);
} catch (err) {
console.log("transformResponse-err", err);
}
}
}
]
})
const codeMessage = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '⼀个请求已经进⼊后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进⾏新建或修改数据的操作。',
401: '⽤户没有权限(令牌、⽤户名、密码错误)。',
403: '⽤户得到授权,但是访问是被禁⽌的。',
404: '发出的请求针对的是不存在的记录,服务器没有进⾏操作。',
405: '请求⽅法未允许',
406: '请求的格式不可得。',
408: '请求超时',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建⼀个对象时,发⽣⼀个验证错误。',
500: '服务器发⽣错误,请检查服务器。',
501: '⽹络未实现',
502: '⽹关错误。',
503: '服务不可⽤,服务器暂时过载或维护。',
504: '⽹关超时。',
505: 'http版本不⽀持该请求'
};
// 2. 添加请求
quest.use(config => {
if (config.url) {
config.headers = {
...config.headers,
timeStamp: new Date().getTime(), // 毫秒数
token: getItem("authToken") || ""
}
// 必须为开发环境,api内的mock开关开启才⽣效
if (v.NODE_ENV === "development" && inUseMockdata && k && kUrl) { // mock ⽣效路径
config.url = kUrl
}
// 请求路径增加时间戳,防⽌命中缓存
config.url += `?timeStamp=${config.headers.timeStamp}`
return config;
} else {
ject('接⼝不合法');
}
}, error => {
// 对请求错误做些什么
console.log('request-err', error);
<(error);
ject(error);
});
let retry = 2 // 重发次数
let retryDelay = 200 // 重发时延
// 3. 添加响应
sponse.use(response => {
// 对响应数据做点什么
return response.data;
}, error => {
// 对响应错误做点什么
console.log('response-err', error);
/*****
* 接收到异常响应的处理开始
* 跨域存在获取不到状态码的情况
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论