安全规范
请求报文和响应报文采用对称加密方式
报文采用MD5+SHA的签名方式,具体签名字段参照报文里的SIGN字段说明,签名使用的工具包后面一并提供,按照说明使用即可。
SHA安全签名机制说明
MD5+SHA安全签名机制是对接方和开发方约定一个签名key,每次在做签名时将参数包括key先进行sort排序拼接成一个待签名字符串,经MD5加密运算后得到一个加密字符串,然后在对该加密字符串做SHA加密运算后得到一个签名串,对接方和开发方通过在检验时先对参数进行相同规则的排序并拼接成字符串进行MD5加密,得到MD5密文,然后对得到的密文字段进行SHA加密得到一个签名串,两个签名串经比对后确定是否一致,如果一致,则签名通过。
请求时签名
先通过约定好的排序规则对请求参数进行排序,并形成一个字符串,对字符串进行MD5的加密,得到密文,再将得到的密文和约定好的密钥,通过SHA加签处理进行生成一个签名串,并将得到的签名串放入sign字段
通知和返回时验证签名
对请求参数进行相同规则的排序并拼接成字符串进行MD5加密,得到MD5密文,然后对得到的密文字段进行SHA加密得到一个签名串,两个签名串经比对后确定是否一致,如果一致,则签名通过
加签参数:
我需要给第三方提供:
//传递的url
http://。。。。。。。
//规定好的ak值
private String accessKey;
//双方规定好的所需要的参数
private String ***;
//双方规定好的密钥
private String secret;
验证的时候:
//加签过后的签名
private String sign;
//规定好的ak值
private String accessKey;
//双方规定好的所需要的参数
private String ***;
//双方规定好的密钥
private String secret;
加密示例:
数据加签:
/**
* 数据加签demo
*/
public static void signDemo(){
//需要加签的key
String key = "****";
//需要加签的密钥
String secret = "****";
//携带的请求参数
Map<String, String> data = new HashMap<>();
data.put("sign","");//加签的时候 签名参数可以置空
data.put("所需要传递的参数","xxx");
data.put("所需要传递的参数", "xxx");
data.put("accessKey", "xxx");//双方所规定的ak值
//先进行排序和MD5加密(下面是特定的方法,在后面代码块中会有体现)
String signature = HmacSHA1Signer.generateSignature(data);
//使用加签工具
String sign = HmacSHA1Signer.signString(signature, secret);
System.out.println("加签完成:"+sign);
}
数据验签
/**
* 数据验签demo
*/
public static void checkSignDemo(){
// 1 获取参数传递的签名和ak值
String accessKey = request.getAccessKey();
String sign = request.getSign();
// 2 通过key去查询对应的密钥
//查询到需要加签的密钥
String secret = "****";
//处理请求参数
Map<String, String> data = new HashMap<>();
//构造当前签名所需要的参数
data.put("sign","");//url传递过来的签名信息
data.put("请求url所携带的参数",request.getUserMobile());
data.put("请求url所携带的参数",request.getUserNickname());
data.put("accessKey",request.getAccessKey());//url传递过来的ak值
//排序和生产MD5密文
String signature = HmacSHA1Signer.generateSignature(data);
//生成签名
String mySign = HmacSHA1Signer.signString(signature, authinfo.getAccessSecret());
//验证
boolean b = mySign..equals(sign);
System.out.println("验签结果:"+b);
}
加签所使用的工具类:
/**
* HmacSHA1 加签包
*
* @author dacongming
* @version V1.0.0
*/
public class HmacSHA1Signer {
private static final String ALGORITHM_NAME = "HmacSHA1";
public static final String ENCODING = "UTF-8";
/**
*
* @methodName: generateSignature
* @param: [data, key, signType]
* @describe: 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
* @auther: dacongming
* @date: 2021/11/11 11:11
**/
public static String generateSignature(Map<String, String> data) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if(null != data.get(k)) {
// 参数值为空,则不参与签名
if (data.get(k).trim().length() > 0) {
if(k.equals("sign")){
continue;
}
//将排序之后的参数进行拼接
sb.append(k).append("=").append(data.get(k).trim()).append("&");
}
}
}
//去除最后一个&符号
String md5String = MD5(sb.substring(0,sb.length()-1)).toUpperCase();
return md5String;
}
/**
*
* @methodName: MD5
* @param: [data]
* @describe: 生成 MD5
* @auther: dacongming
* @date: 2021/11/11 11:11
**/
public static String MD5(String data) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}
/**
* 获取加签值
* @param stringToSign
* @param accessKeySecret
* @return
*/
public static String signString(String stringToSign, String accessKeySecret) {
try {
Mac mac = Mac.getInstance(ALGORITHM_NAME);
mac.init(new SecretKeySpec(
accessKeySecret.getBytes(ENCODING),
ALGORITHM_NAME
));
byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING));
return DatatypeConverter.printBase64Binary(signData);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) {
throw new IllegalArgumentException(e.toString());
}
}
public String getSignerName() {
return "HMAC-SHA1";
}
public String getSignerVersion() {
return "1.0";
}
public String getSignerType() {
return null;
}
}
结束
如果有哪些不对的地方,请多多指教