简介
通信接口加密多用于POST请求中;本文介绍通信接口采用crypt接口进行参数加密。
协议说明
- 所有接口均采用http(https)协议进行通讯,服务端提供http和https协议支持,客户端建议采用https协议
- 所有接口除共通参数设置在header部外,其余请求参数,均以json数据格式放置在request body中,传输到服务端
- 所有接口响应均返回json格式数据
- 所有接口请求及响应均采用utf-8编码
取得动态参数加密
- 通过get请求获取服务端动态key、根据动态key进行Post中body加密,赋值给给参数encryptData。服务端使用key以后,该key将作废,并设定key的超时时间。
优点:保证加密的安全性,每次获取动态key,超时、重复使用key 则无效;
缺点:每次发起请求则请求两次(get取key,post加密);
方案:可以调整为每次页面加载时取key,只判断使用一次key去掉实效性判断。
首次采用客户端加密,后采用用户认证加密
签名计算
1.待签名参数:
clientVersion (格式:0.0.1)
timestamp (服务端时间)
expireTime (毫秒)
clientNonce (随机字符串)
2.计算签名
- 先对 待签名参数按照字段名的ascii码从小到大排序
- 按照排序后,顺序将参数名与参数值依次拼接成字符串
var data = {
clientVersion: '0.0.1',
timestamp: 1526354611209,
expireTime: 10000, // 10s
clientNonce: 'B6F74A83BACF97D5AC24AE6573A4C8AA703F98D9',
// token:'7D5AC24AE6573A4C' //如果已经登录需要token
};
var keys = Object.keys(data).sort();
var str = '';
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
str += key + '=' + data[key];
if (i < keys.length - 1) str += '&';
}
排序后拼接的字符串最终为:
clientNonce=B6F74A83BACF97D5AC24AE6573A4C8AA703F98D9&clientVersion=0.0.1&expireTime=10000×tamp=1526354611209
- 获取签名(SHA1)使用clientNonce进行SHA1加密获取签名
// 前端sha1算法
var signature = CryptoJS.SHA1(str);
signature = signature.toString();
// 最终值为
ecbd4e64791cb1fc8f7c43f41a71bac7859f9647
// 后端sha1算法
String sign = crypt.sha1.shaHex(signature);
// 最终值为
ecbd4e64791cb1fc8f7c43f41a71bac7859f9647
3.根据签名加密上传数据
/**
* 加密
* @param plaintText
* @param key (key为获取到的签名)
* @returns {*}
*/
encrypt: function (plaintText, key) {
if (!CryptoJS) {
wx.showModal({
content: 'CryptoJS no defiend.',
showCancel: false
});
return;
}
if (!key) {
wx.showModal({
content: 'key no defiend.',
showCancel: false
});
return;
}
if (typeof plaintText === 'object') {
plaintText = JSON.stringify(plaintText);
}
key = CryptoJS.enc.Utf8.parse(key);
plaintText = CryptoJS.enc.Utf8.parse(plaintText);
const ciphertext = CryptoJS.AES.encrypt(plaintText, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return ciphertext.toString();
}
4.最终向服务器上传数据格式:
http请求参数:
- 不包括token表示未登陆,包括表示登陆 (false/true均为字符串,浏览器不识别boolean)
- 包括cipher text 则服务端进行加密处理,否则正常取值
body : {
clientVersion: '0.0.1',
timestamp: 1526354611209,
expireTime: 10000, // 10s
clientNonce: 'B6F74A83BACF97D5AC24AE6573A4C8AA703F98D9',
ciphertext: encrypt({ name: '测试' }, signature),
// token:'7D5AC24AE6573A4C' //如果已经登录需要token
}
请求方案
加密请求将作为通用请求方式进行交互,交互加密方式分为登录,未登录两种:
未登录
未登录时,此时待签名参数不包含token。
未登录时,此时发送请求Body不携带token。
登录
登录时,此时待签名参数包含token。
登录时,此时发送请求Body携带token。
通过body中参数 ciphertext 值进行是否加密的判断:
1 、当存在ciphertext时,将对body中ciphertext数据进行ECB 方法加密。传递参数为:
{
clientVersion: '0.0.1',
timestamp: 1526354611209,
expireTime: 10000, // 10s
clientNonce: 'B6F74A83BACF97D5AC24AE6573A4C8AA703F98D9',
ciphertext: encrypt({ name: '测试' }, signature)
}
2 、当不存在ciphertext时,将不对body数据进行ECB加密
{
clientVersion: '0.0.1',
timestamp: 1526354611209,
expireTime: 10000, // 10s
clientNonce: 'B6F74A83BACF97D5AC24AE6573A4C8AA703F98D9',
name: '测试'
}
Header参数说明
- h_noSignatureCheck(是否进行加密处理)
- clientVersion (格式:0.0.1)
- timestamp (服务端时间)
- expireTime (毫秒)
- clientNonce (随机字符串)
Body参数说明
- token (用户登录后凭证)
- ciphertext (加密参数)
- 其他参数
参考接口地址:
Url: code.google.com/p/crypto-js/wiki/License
网友评论