forked from kidgrow-microservices-platform

克 刘
2020-03-16 549148d90d41a3320bd36d469fd690354c78de58
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package com.kidgrow.common.utils;
 
import com.alibaba.fastjson.JSONObject;
import com.kidgrow.common.constant.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
 
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
 
/**
 * 石家庄喜高科技有限责任公司 版权所有 © Copyright 2020<br>
 *
 * @Description: <br>
 * @Project: <br>
 * @CreateDate: Created in 2020/2/4 14:00 <br>
 * @Author: <a href="4345453@kidgrow.com">liuke</a>
 */
@Slf4j
public class SignatureUtils {
    /**
     * 5分钟有效期
     */
    private final static long MAX_EXPIRE = 5 * 60;
 
    public static void main(String[] args) throws Exception {
        String clientSecret = "0osTIhce7uPvDKHz6aa67bhCukaKoYl4";
        //参数签名算法测试例子
        HashMap<String, String> signMap = new HashMap<String, String>();
        signMap.put("APP_ID", "1552274783265");
        signMap.put("SIGN_TYPE", SignType.SHA256.name());
        signMap.put("TIMESTAMP", DateUtils.getCurrentTimestampStr());
        signMap.put("NONCE",RandomValueUtils.randomAlphanumeric(16));
        String sign = SignatureUtils.getSign(signMap, clientSecret);
        System.out.println("签名结果:" + sign);
        signMap.put("SIGN", sign);
        System.out.println("签名参数:" + JSONObject.toJSONString(signMap));
        System.out.println(SignatureUtils.validateSign(signMap, clientSecret));
    }
 
    /**
     * 验证参数
     *
     * @param paramsMap
     * @throws Exception
     */
    public static void validateParams(Map<String, String> paramsMap) throws Exception {
        Assert.hasText(paramsMap.get(CommonConstant.SIGN_APP_ID_KEY), "签名验证失败:APP_ID不能为空");
        Assert.hasText(paramsMap.get(CommonConstant.SIGN_TIMESTAMP_KEY), "签名验证失败:TIMESTAMP不能为空");
        Assert.hasText(paramsMap.get(CommonConstant.SIGN_SIGN_KEY), "签名验证失败:SIGN不能为空");
 
        String timestamp = paramsMap.get(CommonConstant.SIGN_TIMESTAMP_KEY);
        Long clientTimestamp = Long.parseLong(timestamp);
        Long currentTimestamp = System.currentTimeMillis()/1000;
        if ((currentTimestamp - clientTimestamp) > MAX_EXPIRE) {
            throw new IllegalArgumentException("签名验证失败:TIMESTAMP已过期");
        }
    }
 
    /**
     * @param paramsMap     必须包含
     * @param appid
     * @return
     */
    public static boolean validateSign(Map<String, String> paramsMap, String appid) {
        try {
            validateParams(paramsMap);
            String sign = paramsMap.get(CommonConstant.SIGN_SIGN_KEY);
            //重新生成签名
            String signNew = getSign(paramsMap, appid);
            //判断当前签名是否正确
            if (signNew.equals(sign)) {
                return true;
            }
        } catch (Exception e) {
            log.error("validateSign error:{}", e.getMessage());
            return false;
        }
        return false;
    }
 
 
    /**
     * 得到签名
     *
     * @param paramMap     参数集合不含appSecret
     *                     必须包含appId=客户端ID
     *                     signType = SHA256|MD5 签名方式
     *                     timestamp=时间戳
     *                     nonce=随机字符串
     * @param appid 验证接口的clientSecret
     * @return
     */
    public static String getSign(Map<String, String> paramMap, String appid) {
        if (paramMap == null) {
            return "";
        }
        //排序
        Set<String> keySet = paramMap.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
 
        for (String k : keyArray) {
            if (k.equals(CommonConstant.SIGN_SIGN_KEY)) {
                continue;
            }
            if (paramMap.get(k).trim().length() > 0) {
                // 参数值为空,则不参与签名
                sb.append(paramMap.get(k).trim());
            }
        }
        String signStr = signStr = EncryptUtils.md5Hex(sb.toString()).toLowerCase();
 
        return signStr;
    }
 
 
    public enum SignType {
        MD5,
        SHA256;
 
        public static boolean contains(String type) {
            for (SignType typeEnum : SignType.values()) {
                if (typeEnum.name().equals(type)) {
                    return true;
                }
            }
            return false;
        }
    }
 
}