Java 三方接口PHP写法;doHmacSHA2; 将字节数组转换成16进制字符串;Mac.getInstance;HmacSHA256;

发布时间 2023-05-08 10:22:22作者: 一杯热水
先看一段 Java 代码,一个签名过程
  1 package com.sixents.bss.filter;
  2 
  3 
  4 import org.apache.http.HttpEntity;
  5 import org.apache.http.NameValuePair;
  6 import org.apache.http.client.entity.UrlEncodedFormEntity;
  7 import org.apache.http.client.methods.CloseableHttpResponse;
  8 import org.apache.http.client.methods.HttpPost;
  9 import org.apache.http.impl.client.CloseableHttpClient;
 10 import org.apache.http.impl.client.HttpClients;
 11 import org.apache.http.message.BasicNameValuePair;
 12 import org.apache.http.util.EntityUtils;
 13 
 14 import javax.crypto.Mac;
 15 import javax.crypto.spec.SecretKeySpec;
 16 import java.nio.charset.Charset;
 17 import java.security.InvalidKeyException;
 18 import java.security.NoSuchAlgorithmException;
 19 import java.util.*;
 20 import java.util.Map.Entry;
 21 
 22 /**
 23  * @author zy
 24  * date 2021-08-19
 25  */
 26 public class demoTest {
 27 
 28 
 29     public static void main(String[] args) throws Exception{
 30         String sik = "0797517995";//请填写您申请的sik
 31         String sis = "inuHf8DvK+z3lqor168yDcx60lAcMCtAagcchaxWRlvWTq6WImQ4zQVEibnwhegShrQNft8zvGXA" +
 32                 "C6TSH4gjQzmaTSeNzugv0dTSj9m2eiQ=";//请填写您申请的sis
 33         String apiName = "get-account-list";// 访问的API接口名称
 34         String apiPath = "/rest/" + apiName + "/" + "sik" + "/"+sik;// API路径,注意没有问号
 35         // 参数列表(加签的时候需要进行字典序升序排序)
 36         Map<String, String> paramMap = new HashMap<String, String>();
 37         paramMap.put("pageNum", "1");
 38         paramMap.put("pageSize", "20");
 39         paramMap.put("serverType", "1");
 40      // 毫秒级时间戳,一定是毫秒级!重要!!!
 41         String timestamp = String.valueOf(System.currentTimeMillis());
 42         System.out.println("时间戳:"+timestamp);
 43         String signatureStr = demoTest.doHmacSHA2(apiPath, paramMap, sis, timestamp);
 44         System.out.println("加签值:"+signatureStr);//打印sign值
 45 
 46         String qxwzUrl = "http://localhost:21009";//服务器地址
 47         String queryUrl = qxwzUrl + apiPath + "?_sign=" + signatureStr;
 48         System.out.println(queryUrl);
 49 
 50         //发送http请求,获取返回值
 51         doHttpPost(queryUrl,paramMap,timestamp);
 52     }
 53 
 54     public static void doHttpPost(String url,Map<String, String> paramMap, String timestamp) throws Exception {
 55         CloseableHttpClient httpClient = HttpClients.createDefault();
 56         HttpPost httpPost = new HttpPost(url);
 57         httpPost.setHeader("content-type", "application/json");
 58         httpPost.setHeader("wz-acs-timestamp", timestamp);//此处注意加上时间戳,否则http请求将无效
 59         List<NameValuePair> nvps = new ArrayList<NameValuePair>();
 60         for (Map.Entry<String, String> entry : paramMap.entrySet()){
 61             if (entry.getValue() == null) continue;
 62             nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
 63         }
 64         httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));//处理中文编码的问题
 65 
 66 
 67         try {
 68             CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpPost);
 69             try {
 70                 HttpEntity entity = response.getEntity();
 71                 if (entity != null) {
 72                     System.out.println("返回值:"+EntityUtils.toString(entity));
 73                     /*
 74                      * 此处针对返回结果进行不同的处理
 75                      */
 76                     EntityUtils.consume(entity);
 77                 }
 78             } finally {
 79                 response.close();
 80             }
 81 
 82         } catch (Exception e) {
 83             e.printStackTrace();
 84         }finally {
 85             if (httpPost != null) {
 86                 httpPost.releaseConnection();//释放资源
 87             }
 88             if(httpClient != null){
 89                 httpClient.close();//释放资源
 90             }
 91         }
 92     }
 93 
 94     /*
 95      * 将字节数组转换成16进制字符串
 96      * */
 97     public static String encodeHexStr(final byte[] bytes){
 98         if (bytes == null) {
 99             return null;
100         }
101         char[] digital  = "0123456789ABCDEF".toCharArray();
102         char[] result = new char[bytes.length * 2];
103         for (int i = 0; i < bytes.length; i++) {
104             result[i * 2] = digital[(bytes[i] & 0xf0) >> 4];
105             result[i * 2 + 1] = digital[bytes[i] & 0x0f];
106         }
107         return new String(result);
108     }
109 
110     /*
111      * 加签算法
112      * */
113     public static <T> String doHmacSHA2(String path, Map<String, T> params, String key, String timestamp) {
114 
115         List<Map.Entry<String, T>> parameters = new ArrayList<Map.Entry<String,T>>(params.entrySet());
116         SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA256");
117         Charset CHARSET_UTF8 = Charset.forName("UTF-8");
118         Mac mac;
119         try {
120             mac = Mac.getInstance("HmacSHA256");
121             mac.init(signingKey);
122         } catch (NoSuchAlgorithmException e) {
123             throw new IllegalStateException(e.getMessage(), e);
124         } catch (InvalidKeyException e) {
125             throw new IllegalStateException(e.getMessage(), e);
126         }
127         if(path != null && path.length() > 0){
128             mac.update(path.getBytes(CHARSET_UTF8));
129         }
130         if(parameters != null){
131             Collections.sort(parameters, new MapEntryComparator<String, T>());
132             for (Map.Entry<String, T> parameter : parameters) {
133                 byte[] name = parameter.getKey().getBytes(CHARSET_UTF8);
134                 Object value = parameter.getValue();
135                 if(value instanceof Collection){
136                     for (Object o : (Collection)value){
137                         mac.update(name);
138                         if(o != null){
139                             mac.update(o.toString().getBytes(CHARSET_UTF8));
140                         }
141                     }
142                 }else{
143                     mac.update(name);
144                     if(value != null){
145                         mac.update(value.toString().getBytes(CHARSET_UTF8));
146                     }
147                 }
148             }
149         }
150         if(timestamp != null && timestamp.length() > 0){
151             mac.update(timestamp.toString().getBytes(CHARSET_UTF8));
152         }
153         return encodeHexStr(mac.doFinal());
154     }
155 }
156 
157 /*
158  * Map参数排序类
159  * */
160 
161 class MapEntryComparator<K, V> implements Comparator<Map.Entry<K, V>> {
162 
163     @Override
164     public int compare(Entry<K, V> o1, Entry<K, V> o2) {
165         if (o1 == o2) {
166             return 0;
167         }
168         final String k1 = o1.getKey().toString();
169         final String k2 = o2.getKey().toString();
170         int l1 = k1.length();
171         int l2a = k2.length();
172         for (int i = 0; i < l1; i++) {
173             char c1 = k1.charAt(i);
174             char c2;
175             if (i < l2a) {
176                 c2 = k2.charAt(i);
177             } else {
178                 return 1;
179             }
180             if (c1 > c2) {
181                 return 1;
182             } else if (c1 < c2) {
183                 return -1;
184             }
185         }
186         if (l1 < l2a) {
187             return -1;
188         }else if(l1 == l2a) {
189             return 0;
190         }else {
191             return -1;
192         }
193     }
194 
195 }

 

PHP 写法如此简单:

 1     private function get_sign($path, $params, $timestamp)
 2     {
 3         if (empty($params)) {
 4             die('miss params');
 5         }
 6 
 7         // 排序
 8         ksort($params);
 9 
10         $ctx = hash_init('sha256', HASH_HMAC, $this->sis);
11 
12         hash_update($ctx, utf8_encode($path));
13       
14         foreach ($params as $key => $value) { // 如果 $value 还是数组再循环一次即可 
15             hash_update($ctx, utf8_encode($key));
16             hash_update($ctx, utf8_encode($value));
17         }
18 
19         hash_update($ctx, utf8_encode($timestamp));
20 
21         return strtoupper(hash_final($ctx));
22     }
23