基于appKey和md5的接口加密验签
1.为什么要验签?
内部:token鉴权;
对外服务:利用appKey和md5来进行接口验签;
2.验签思路
- 为某个接口调用者,生成 1个appKey加1个secret秘钥
- 调用者调用接口时,根据请求参数+appKey+secret秘钥,将报文键值根据首字母排序,然后生成一个sign签名
- 调用者,请求接口的时候,把sign签名和appKey 传递给服务端
- 服务端收到请求后,根据得到的appKey,去查询对应的secure秘钥
- 服务端,把sign签名从参数中移除,和客户端做一样的事情,根据请求参数+appKey+secret秘钥,也计算一个sign签名
- 服务端把自己计算得出的sign签名,和接口调用者传递过来的sign签名进行比较,如果一致,则证明这个接口的调用者,是合法的身份
3、需求
服务方需要提供:appKey,secretKey 并以键值对方式绑定;
签名机制:
请求报文中除了sign 全部参数都需要参与签名生成sign;
报文参数:
{
"access_key":"psbc",
"username":"test",
"pwd":"123",
"age":"2"
}
待签名字符:
需要对参数组按照首字母排序,再将参数根据&连接起来。
access_key=psbc&age=2&pwd=123&username=test
MD5 签名
签名是需要secretKey 参与签名,要求将secretKey 通过& 连接再待签名字符串形成最终待签名字符串;
access_key=psbc&age=2&pwd=123&username=test&psbc
最终形成一个sign,
最终请求报文:
{
"access_key":"psbc",
"username":"test",
"pwd":"123",
"age":"2",
"sign":"sdjsfjkdhfjkhdjkghkhg"
}
4、实现
1、获取请求参数
request 获取请求体报文,具体根据接入方式实现
String requestData = requestBody
log.info(requestData )
2、json转map
将报文转换成map ,方便后续删除sign 并根据首字母排序
Map maps = (Map)JSON.parse(requestData);
for(Object map : maps.entrySet){
log.info(((Map.Entry)map).getKey())
})
3、通过access_key 获取secretKey
(数据库维护或者配置文件维护 加密钥匙对)
String secretKey = 'psbc';
4、获取商家sign
待会需要对比服务端生成的sign和商家的sign 对比,暂存。
String signIt = (String)maps.get("sign")
5、移除商家sign
maps.remove("sign")
6、报文排序
将报文根据键首字母排序
maps = mapConver(maps);
public static Map mapConver(Map<String,String> map){
if(map==null || map.isEmpty()){
return null;
}
Map<String,String> sortMap = new TreeMap<String,String>();
sortMap.putAll(map);
return sortMap;
}
7、格式化字符串
String str = "";
for(Map.Entry m : maps.entrySet()){
str = str + m.getKey()+"="+m.getValue()+"&";
str = str+secretKey;
}
待加密字符串:
username=test&pwd=123&psbc
8、加密核对
String signMe = DigestUtils.md5Hex(str);
if(signMe.equle(sign)){
""验签成功""
}