avatar

目录
学习记录:接口参数MD5算法校验

签名算法过程

对除签名外的所有请求参数按key做ASCII升序排列,value无需编码。

例如:一共有三个参数,a=10,b=11,c=12,那么再加上时间戳之后就是四个参数,按Key做ASCII升序排列之后,得到拼装的字符串,a10b11c1212345678,当然加不加参数名这些规则由你来定

用约定好的appkey来拼装到字符串的头部和尾部:appkey+a10b11c1212345678+appkey然后进行32位MD5加密,最后转大写。

这只是你需要接受的sign签名,除此之外,还需要接受包括在sign之中的所有参数,例如时间戳等等。

在你接受到参数之后,你同样要再次进行一遍MD5加密,然后与sign进行匹配,如果相同的话则签名正确,否则签名失败。

以下是例子:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* MD5加密工具类
* @param src 需要加密的字符串
* @return
*/
public class EncryptionUtil {
public final static String MD5(String src) {
char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
try {
byte[] btInput = src.getBytes("UTF-8");
MessageDigest mdInst = MessageDigest.getInstance("MD5");
mdInst.update(btInput);
byte[] md = mdInst.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

controller:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RestController
@RequestMapping("/scanCode")
public class ScanCodeBuyController {

@Autowired
private ScanCodeBuyService scanCodeBuyService;

/**
* 扫码购
* @param 'sign' 签名
* @param 'productname' 商品名称
* @param 'productno' 商品编号
* @param 'timestamp' 时间戳
* @param 'page' 当前页码
* @param 'pageSize' 每页条数
* @return
*/
@PostMapping("/provideProduct")
public ResultMsg provideProduct(@RequestBody Map<String,String> map){
return scanCodeBuyService.provideProduct(map);
}

}

service就不贴出来了

以下是serviceImpl:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
@Service
public class ScanCodeBuyServiceImpl implements ScanCodeBuyService {

private Logger logger = LoggerFactory.getLogger(this.getClass());

@Value("${product.ScanCodeBuy.MD5Key}")
private String MD5Key; //MD5约定的key我放在了数据库中

@Autowired
private ESIndexService esIndexService; //feign中用到的其他服务的方法

@Override
public ResultMsg provideProduct(Map<String, String> map) {
//ResultMsg是我的一个数据模型DTO
//验证签名
ResultMsg msg = checkSign(map);
ResultMsg esMsg = new ResultMsg();
if (! msg.getResult()){
return msg;
}
try {
//........逻辑代码
}catch (Exception e){
logger.info("provideProduct======"+e);
esMsg.setRetcode("ES");
esMsg.setMsg("内部错误");
esMsg.setResult(false);
return esMsg;
}
return esMsg;
}

/**
* 签名校验
* @param sign
* @return
*/
public ResultMsg checkSign(Map<String, String> map){
ResultMsg msg = new ResultMsg();
if (StringUtils.isEmpty(map.get("productname"))) {
msg.setRetcode("P1");
msg.setMsg("productname不能为空");
msg.setResult(false);
return msg;
}
if (StringUtils.isEmpty(map.get("sign"))) {
msg.setRetcode("S1");
msg.setMsg("sign不能为空");
msg.setResult(false);
return msg;
}
if (StringUtils.isEmpty(map.get("productno"))) {
msg.setRetcode("P1");
msg.setMsg("productno不能为空");
msg.setResult(false);
return msg;
}
if (StringUtils.isEmpty(map.get("timestamp"))) {
msg.setRetcode("T1");
msg.setMsg("timestamp不能为空");
msg.setResult(false);
return msg;
}
if (StringUtils.isEmpty(map.get("page"))) {
msg.setRetcode("P1");
msg.setMsg("page不能为空");
msg.setResult(false);
return msg;
}
if (StringUtils.isEmpty(map.get("pageSize"))) {
msg.setRetcode("P1");
msg.setMsg("pageSize不能为空");
msg.setResult(false);
return msg;
}
String md5 = EncryptionUtil.MD5(MD5Key+map.get("page")
+map.get("pageSize")
+map.get("productname")
+map.get("productno")
+map.get("timestamp")
+MD5Key).toUpperCase();
logger.info("product===ScanCodeBuy==========md5本地签名"+md5);
logger.info("product===ScanCodeBuy==========sign传入签名"+map.get("sign"));
if (md5.equals(map.get("sign"))){
msg.setMsg("签名匹配");
msg.setResult(true);
return msg;
} else {
msg.setRetcode("S2");
msg.setMsg("签名不匹配");
msg.setResult(false);
return msg;
}
}

}
文章作者: 十四礼
文章链接: https://lemcoo.top/2019/12/201912301251-int/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 观礼塘

评论