前端请求参数混淆方案分享

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

写在前面

在进行接口请求时,我们希望携带的数据不希望是以明文的方式提交的,也就是需要对参数做一些混淆或者加密处理,后端拿到数据后再进行解密,得到真实数据。

其目的是为了保护数据的安全,以及提高被识破成明文的门槛。在例如用户登录的接口请求中,如果账号和密码是以明文传输的,会容易导致一些安全性问题,因此前端参数混淆非常有必要,这里分享一个自用的方案。

什么接口的参数需要做处理

从安全角度出发,这里一致认为,只要是对数据库有新增、修改、删除操作的,一律需要做混淆/加密,这一类接口,多为post请求。

而对于get请求,如果是规范化的接口,一般只是获取数据,不会对数据库有直接的操作,故不需要做参数处理。

当然还有post请求,却不希望做参数处理的接口,需要特殊处理,以及在开发环境中,为了方便调试,也不需要做处理。

参数处理算法

这里使用的方案是,先将原始数据处理为query形式的字符串,然后将其使用随机字符串作为密钥,参与Aes加密,并截取特定的字符串,作为原始密钥,再进行一次Aes加密,最后将原始密钥使用与后端约定好的公钥进行Rsa加密处理,具体算法如下:

/**
* 加密请求数据
* @param {Object} rawData 原始数据
* @returns {data, key}
*/
export function encryptRequestData(rawData) {
 // 字典排序并赋值
 var result = {}, str = [], arr = Object.keys(rawData).sort();
 arr.map(m => { result[m] = rawData[m] });

 // 处理成 query 形式字符串
 for (var p in result)
     result.hasOwnProperty(p) && str.push(encodeURIComponent(p) + "=" + encodeURIComponent(result[p]));
     result = str.join("&");

 // 参与 Aes 加密的密钥,将处理后的字符串用 16 位随机码对称加密,再从第 3 位开始获取 16 位原始密钥
 const rawKey = aesEncrypt(result, randomString(16)).substr(3, 16);


 // 输出最后的加密参数
 const data = aesEncrypt(JSON.stringify(rawData), rawKey);
 const key = rsaEncrypt(rawKey);

 return { data, key }
}
复制代码

参数处理时机

我们需要在请求拦截的时候对参数做混淆处理,这里只针对post请求以及非本地环境,另外,在实例上还增加了uncrypt来标识哪些接口可以不参与处理。

// 请求拦截
instance.interceptors.request.use(
    config => {
        config.headers.contentType = "application/x-www-form-urlencoded"

        const token = local.get('token')
        token && (config.headers.Authorization = token)

        const { method, uncrypt = false, data = {} } = config;
        (method === 'post' && !uncrypt && cfg.NODE_ENV === 'development') && (config.data = encryptRequestData(data));

        return config
    },
    error => Promise.error(error)
)
复制代码

欢迎阅读其它文章

猜你喜欢

转载自juejin.im/post/7083091933454663710