接口签名工具类


登陆接口签名方案:
客户端在Header中传递时间戳("curTime")、入参的md5值("md5")和校验和("checkSum")等3个参数;
(1)md5值:
客户端将请求入参使用md5加密并转成十六进制的字符串形式,放入Header;

(2)校验和:
客户端将APPSECRET(暂时写死 "67wGmp7PdhwEp9I4"), md5, curTime等3个参数使用sha1加密并转成十六进制的字符串形式,放入Header();

注意事项:
入参中的各项参数首字母必须按照字典排序,不能使用格式化后的json, 否则校验不通过.

sha1密文示例:7c4a8d09ca3762af61e56520943dc26494f8941b
md5密文示例:e10adc3949ba56abbe56e057f20f883e

--------------------------------------------
测试手机号登陆接口示例[已测试通过]:
header部分:
curTime:1532152323277
md5:b580f998587cbfa05ab693581b750a3c
checkSum:485c555005e0664790ff69583cbcb75394f8d4ed

入参部分[注意json不要格式化]:
{"channelType":"9","checkKey":"123456","devId":"87cbfa05ab093581b75","equipmentType":"2","imageCode":"dh59Ds","phone":"13966672478","smsCode":"985264"}

如果签名校验失败会返回:
{
"code": 200,
"errorCode": "549",
"errorMsg": "签名验证失败",
"sid": "6d4a871da5094e4799f0e8cc0b1183461532153216096",
"success": true
}
--------------------------------------------

  1 import com.alibaba.fastjson.JSON;
  2 import com.alibaba.fastjson.serializer.SerializerFeature;
  3 import org.springframework.util.StringUtils;
  4 
  5 import java.security.MessageDigest;
  6 import java.util.HashMap;
  7 import java.util.Map;
  8 
  9 /**
 10  * 签名工具
 11  *
 12  * @Author: syj
 13  * @CreateDate: 2018/7/20 17:32
 14  */
 15 public class SignUtil {
 16 
 17     /**
 18      * APP密码
 19      */
 20     private static final String QMALLL_LOGIN_APPSECRET = "DkkGmp3PdhwEp6I8";
 21 
 22     /**
 23      * 校验签名
 24      *
 25      * @param curTime     时间戳
 26      * @param requestBody 请求参数
 27      * @param md5         请求参数的md5值
 28      * @param checkSum    校验和(将appsecret、请求参数md5值和时间戳采用sha1加密)
 29      * @return
 30      */
 31     private boolean doCheck(String curTime, String requestBody, String md5, String checkSum) {
 32         if (StringUtils.isEmpty(md5) || StringUtils.isEmpty(checkSum)) {
 33             return false;
 34         }
 35         String verifyMD5 = SignUtil.md5(requestBody);
 36         String verifyChecksum = SignUtil.checkSum(QMALLL_LOGIN_APPSECRET, verifyMD5, curTime);
 37         return md5.equals(verifyMD5) && checkSum.equals(verifyChecksum) ? true : false;
 38     }
 39 
 40     /**
 41      * 计算并获取CheckSum
 42      * 使用sha1加密
 43      *
 44      * @param appSecret
 45      * @param nonce
 46      * @param curTime
 47      * @return
 48      */
 49     public static String checkSum(String appSecret, String nonce, String curTime) {
 50         return encode("sha1", appSecret + nonce + curTime);
 51     }
 52 
 53     /**
 54      * 计算并获取md5值
 55      *
 56      * @param requestBody
 57      * @return
 58      */
 59     public static String md5(String requestBody) {
 60         return encode("md5", requestBody);
 61     }
 62 
 63     public static String encode(String algorithm, String value) {
 64         if (value == null) {
 65             return null;
 66         }
 67         try {
 68             MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
 69             messageDigest.update(value.getBytes());
 70             return getFormattedText(messageDigest.digest());
 71         } catch (Exception e) {
 72             throw new RuntimeException(e);
 73         }
 74     }
 75 
 76     /**
 77      * 把密文转换成十六进制的字符串形式
 78      *
 79      * @param bytes
 80      * @return
 81      */
 82     private static String getFormattedText(byte[] bytes) {
 83         int len = bytes.length;
 84         StringBuilder buf = new StringBuilder(len * 2);
 85         for (int j = 0; j < len; j++) {
 86             buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
 87             buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
 88         }
 89         return buf.toString();
 90     }
 91 
 92     private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
 93 
 94     /**
 95      * 签名测试
 96      */
 97     private static void signTest() {
 98         // 请求时间戳
 99         String curTime = String.valueOf(System.currentTimeMillis());
100 
101         // 模拟请求入参
102         Map<String, Object> map = new HashMap<>();
103         map.put("userName", "admin");
104         map.put("password", "123456");
105         map.put("applicationId", 1L);
106         map.put("otherNickName", "系统管理员");
107         map.put("phone", "15801081566");
108         map.put("verificationCode", "123456");
109         map.put("responseType", "1");
110         map.put("osType", "ios");
111         map.put("mac", "123456789");
112         // 转成json并按字典排序(注意版本:本人使用的fastjson版本为1.2.47)
113         String requestBody = JSON.toJSONString(map, SerializerFeature.MapSortField);
114 
115         // 对请求入参使用md5加密
116         String md5 = SignUtil.md5(requestBody);
117 
118         // 使用sha1加密
119         String checkSum = SignUtil.checkSum(QMALLL_LOGIN_APPSECRET, md5, curTime);
120 
121         //  校验
122         signTest(curTime, requestBody, md5, checkSum);
123     }
124 
125     /**
126      * 加密测试
127      */
128     private static void md5Test(String data) {
129         String sha1 = SignUtil.encode("sha1", data);
130         String md5 = SignUtil.encode("md5", data);
131         System.out.println("sha1密文:" + sha1);
132         System.out.println("md5密文:" + md5);
133     }
134 
135     /**
136      * 测试签名
137      *
138      * @param curTime     时间戳
139      * @param requestBody 请求参数
140      * @param md5         请求参数的md5值
141      * @param checkSum    校验和(将appsecret、请求参数md5值和时间戳采用sha1加密)
142      * @return
143      */
144     public static boolean signTest(String curTime, String requestBody, String md5, String checkSum) {
145         System.out.println("入参:curTime=" + curTime);
146         System.out.println("入参:requestBody=" + requestBody);
147         System.out.println("入参:md5=" + md5);
148         System.out.println("入参:checkSum=" + checkSum);
149         // 计算md5
150         String verifyMD5 = SignUtil.md5(requestBody);
151         // 计算checkSum
152         String verifyChecksum = SignUtil.checkSum(QMALLL_LOGIN_APPSECRET, verifyMD5, curTime);
153 
154         System.out.println("md5值:" + verifyMD5);
155         System.out.println("校验和:" + verifyChecksum);
156 
157         // 比较md5,checkSum是否一致
158         boolean checkResult = md5.equals(verifyMD5) && checkSum.equals(verifyChecksum) ? true : false;
159         System.out.println("校验结果:" + checkResult);
160         return checkResult;
161     }
162 
163     /**
164      * 测试
165      *
166      * @param args
167      */
168     public static void main(String[] args) {
169         md5Test("admin");
170         signTest();
171     }
172 
173 }
原文地址:https://www.cnblogs.com/jun1019/p/9345907.html