为了保证http请求数据的安全性和防篡改性。我们通常要对请求参数进行一些加密。
加密规则可以根据双方接口协商定义。这里举一个常用的加密协议例子。
1. sign加密协议
接口协议中通常会提供一个 appKey作为唯一的标识。
appSecret作为接入密钥。
例如:appkey=hh appSecret=39ertfefdsg406c7c36592d42022aaecc
请求路径
http://www.example.com/login
请求参数
appKey hh 合作方平台标识
username 用户名
password 密码
time Unix时间戳(10位)
sign 签名串
2. 加密要求
将筛选的参数按照第一个字符的键值ASCII码递增排序(字母升序排序),如果遇到相同字符则按照第二个字符的键值ASCII码递增排序,以此类推。
将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用&字符连接起来,此时生成的字符串为待签名字符串
生成签名
sign = md5(待签名字符串)
示例
例如:
sign = md5(待签串)
参数表为:
appKey=hs,
username=lzl,
password=88fsdfgsff8fd9ssg99
time=1432432234
待签名字符串为(取排序后的结果,这里key不参与排序):
appKey=hh&password=HG20170113140431206&time=1423212323&key=密钥
3. 处理流程
我们根据加密要求,把要传送的字段进行排序和MD5加密。将加密后的结果和传输的字段一并送过去。
appKey=hh&password=HG20170113140431206&time=1423212323&key=密钥&sign=签名串。
验证方式:
如何保证这条http请求能够正常相应数据呢?提供接口方,也是根据传输的字段进行排序和MD5加密。将加密后的结果verifySign与sign进行
比较。如果相同,就说明是一个正常的请求。反之,就是以非法请求。
代码示例:
public class MD5Utils {
/**
* 参数签名加密
* @param parameters
* @param secret
* @return
*/
public static String signRequest(TreeMap<String,String> parameters,String secret,String charset){
TreeMap<String, String> treeMap = new TreeMap<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
treeMap = (TreeMap<String, String>) parameters;
System.out.println("升序排序结果:"+treeMap);
StringBuffer sb = new StringBuffer();
//把map中的集合拼接成字符串
for(Map.Entry<String, String> entry:treeMap.entrySet()){
String key = entry.getKey();
Object value = entry.getValue();
sb.append(key).append("=").append(value).append("&");
}
sb.append("key").append("=").append(secret);
System.out.println("拼接后的字符:"+sb.toString());
//进行MD5加密
String sign = DigestUtils.md5Hex(getContentBytes(sb.toString(), charset));
System.out.println("加密后的签名:"+sign);
return sign;
}
/**
* @param content
* @param charset
* @return
* @throws SignatureException
* @throws UnsupportedEncodingException
*/
private static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
public static void main(String[] args) {
TreeMap<String,String> treeMap = new TreeMap<>();
treeMap.put("appKey", "hh");
treeMap.put("username", "1335288");
treeMap.put("password", "435rewt32423ewt4325terw");
treeMap.put("time", String.valueOf(System.currentTimeMillis()/1000));
String key = "密钥";
MD5Utils.signRequest(treeMap,key,"utf-8");
}
}