您的位置:首页 > 移动开发

APP通信加密方案

2016-12-16 11:26 190 查看


App版接口与pc版接口的区别:

App版:每次请求都需要携带 appId参数(针对所有接口:登录、未登录接口),所有请求都会经过加密签名校验流程,数据 HTTP / HTTPS加密传输。

Pc版:每次请求无需登录的接口没有参数限制要求,需登录的接口必须传userId、token,token为草根金融后台生成,与XX平台的token无关,数据传输为明文。

共同点:两个版本的接口只在mvc层不同,业务逻辑代码为同一套。所有接口均为无状态,网页端、app端需根据接口返回的结果判断用户当前是否登录。所有请求都要带上 accessFrom 参数

App端通信流程详解:

从上至下,按环节说明:

1. 判断appId、appSecret是否存在

appId:

app设备的唯一标识符,由服务端生成,app每次发送请求时,都需要带上此参数。

appSecret

当前设备的通信私钥,由服务端生成

app端需要同时缓存 appId 、appSecret两个字段,appId、appSecret在服务端会有过期时间,2 种情况下需求重新获取:

一、 服务端返回 secret_pass_time_error字符串时,app端在得知私钥过期,此时需要重新获取并缓存。

二、 App刚启动时

2. 发送请求生成 appId 、appSecret

接口地址:

/XXXX/secret_key/generate.json

返回值:

{"data":{"appId":"0c008f12901c4cd2a689635b8f6de0eepe9il7g0e27hfmir","appSecret":"f9f731c1cfc04bc48cd1b9b631709949"},"success":true}

请求成功后,app端需缓存appId、appSecret,并在以后的请求中始终带上appId字段。

注:

在调用该接口时,由于appSecret未生成,所有全程使用公钥加密,并且在以后其他接口调用中,对于 appId字段,统一使用公钥加密、解密。

3. 加密签名过程

加密算法

Aes + base64

Javaapp端代码示例:

// 用于保存请求的参数名
List<String> keys = newArrayList<String>(param.size() + 1);
// 最终发送到服务器的参数键值对
Map<String, String> requestMap =new HashMap<String,String>();
if (appId !=null) {
requestMap.put(AppIdKey,appId);
keys.add(AppIdKey);
}

/** 加密业务参数(私钥) */
for (Iterator<String>it =
param.keySet().iterator();it.hasNext();) {
String paramKey =
it.next();
// 不对appId进行私钥加密
if (paramKey.equals(AppIdKey)) {
continue;
}
keys.add(paramKey);
String encodeValue = EncryptUtil.aesEncode(param.get(paramKey),appSecret);
requestMap.put(paramKey,encodeValue);
}

/** md5签名(私钥) */
// 先对参数名正序排序
Collections.sort(keys);
StringBuilder sb = new StringBuilder();
for (String
key : keys) {
// 所有参数值相加
sb.append(requestMap.get(key));
}
// 最后加上私钥
sb.append(appSecret);
requestMap.put("sign", Md5Encrypt.md5(sb.toString()));

/** 全局加密(公钥)(包含已用私钥加密过的参数值、未加密的参数名以及appId) */
Map<String, String> encrptyParam =new HashMap<String,String>();
for (Map.Entry<String, String>entry :
requestMap.entrySet()) {
encrptyParam.put(EncryptUtil.aesEncode(entry.getKey(),publicSecret), EncryptUtil.aesEncode(entry.getValue(),publicSecret));
}

/** 发送请求 */
String result = HttpRequestUtil.httpPostAccess(ApiAddress +uri,
encrptyParam,"utf-8");

/** 缓存的appSecret过期,需求重新生成appId、appSecret后再发请求
*/
if ("secret_pass_time_error".equals(result)) {
throw
new
AppScretTimeOutException("密钥过期");
}

/* 解密响应数据(私钥) */
result = EncryptUtil.aesDecode(result,appSecret);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: