腾讯OCR签名算法

avatar
作者
猴君
阅读量:0

云服务器 签名方法 v3-调用方式-API 中心-腾讯云

一,签名算法-官网

copy官网

package com.smcv.customer.service.util;  import org.springframework.http.HttpHeaders;  import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; import java.util.TreeMap;  public class TencentCloudAPITC3Demo {     private final static Charset UTF8 = StandardCharsets.UTF_8;     // 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKIDz8krbsJ5yKBZQpn74WFkmLPx3******* //    private final static String SECRET_ID = System.getenv("TENCENTCLOUD_SECRET_ID");     private final static String SECRET_ID = "AKIDBE4g3B4";     // 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 Gu5t9xGARNpq86cd98joQYCN3******* //    private final static String SECRET_KEY = System.getenv("TENCENTCLOUD_SECRET_KEY");     private final static String SECRET_KEY = "tWt2uXu1uc";      private final static String CT_JSON = "application/json; charset=utf-8";      public static byte[] hmac256(byte[] key, String msg) throws Exception {         Mac mac = Mac.getInstance("HmacSHA256");         SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());         mac.init(secretKeySpec);         return mac.doFinal(msg.getBytes(UTF8));     }      public static String sha256Hex(String s) throws Exception {         MessageDigest md = MessageDigest.getInstance("SHA-256");         byte[] d = md.digest(s.getBytes(UTF8));         return DatatypeConverter.printHexBinary(d).toLowerCase();     }      public static void main(String[] args) throws Exception {         String service = "cvm";         String host = "cvm.tencentcloudapi.com"; //        String region = "ap-guangzhou"; //        String action = "DescribeInstances";         String region = "ap-shanghai";         String action = "SmartStructuralOCRV2";         String version = "2018-11-19";         String algorithm = "TC3-HMAC-SHA256"; //        String timestamp = "1551113065";         String timestamp = String.valueOf(System.currentTimeMillis() / 1000);         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");         // 注意时区,否则容易出错         sdf.setTimeZone(TimeZone.getTimeZone("UTC"));         String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));          // ************* 步骤 1:拼接规范请求串 *************         String httpRequestMethod = "POST";         String canonicalUri = "/";         String canonicalQueryString = "";         String canonicalHeaders = "content-type:application/json; charset=utf-8\n" + "host:" + host + "\n" + "x-tc-action:" + action.toLowerCase() + "\n";         String signedHeaders = "content-type;host;x-tc-action";          String payload = "{\"Limit\": 1, \"Filters\": [{\"Values\": [\"\\u672a\\u547d\\u540d\"], \"Name\": \"instance-name\"}]}";         String hashedRequestPayload = sha256Hex(payload);         String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;         System.out.println(canonicalRequest);          // ************* 步骤 2:拼接待签名字符串 *************         String credentialScope = date + "/" + service + "/" + "tc3_request";         String hashedCanonicalRequest = sha256Hex(canonicalRequest);         String stringToSign = algorithm + "\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;         System.out.println(stringToSign);          // ************* 步骤 3:计算签名 *************         byte[] secretDate = hmac256(("TC3" + SECRET_KEY).getBytes(UTF8), date);         byte[] secretService = hmac256(secretDate, service);         byte[] secretSigning = hmac256(secretService, "tc3_request");         String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();         System.out.println(signature);          // ************* 步骤 4:拼接 Authorization *************         String authorization = algorithm + " " + "Credential=" + SECRET_ID + "/" + credentialScope + ", " + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;         System.out.println(authorization);          TreeMap<String, String> headers = new TreeMap<String, String>();         headers.put("Authorization", authorization);         headers.put("Content-Type", CT_JSON);         headers.put("Host", host);         headers.put("X-TC-Action", action);         headers.put("X-TC-Timestamp", timestamp);         headers.put("X-TC-Version", version);         headers.put("X-TC-Region", region);          StringBuilder sb = new StringBuilder();         sb.append("curl -X POST https://").append(host).append(" -H \"Authorization: ").append(authorization).append("\"").append(" -H \"Content-Type: application/json; charset=utf-8\"").append(" -H \"Host: ").append(host).append("\"").append(" -H \"X-TC-Action: ").append(action).append("\"").append(" -H \"X-TC-Timestamp: ").append(timestamp).append("\"").append(" -H \"X-TC-Version: ").append(version).append("\"").append(" -H \"X-TC-Region: ").append(region).append("\"").append(" -d '").append(payload).append("'");         System.out.println(sb.toString());     }      public static HttpHeaders buildHeader(String payload) throws Exception {         String service = "ocr";         String host = "ocr.tencentcloudapi.com";         String region = "ap-shanghai";         String action = "SmartStructuralOCRV2";         String version = "2018-11-19";         String algorithm = "TC3-HMAC-SHA256";         String timestamp = String.valueOf(System.currentTimeMillis() / 1000);         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");         // 注意时区,否则容易出错         sdf.setTimeZone(TimeZone.getTimeZone("UTC"));         String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));          // ************* 步骤 1:拼接规范请求串 *************         String httpRequestMethod = "POST";         String canonicalUri = "/";         String canonicalQueryString = "";         String canonicalHeaders = "content-type:application/json; charset=utf-8\n" + "host:" + host + "\n" + "x-tc-action:" + action.toLowerCase() + "\n";         String signedHeaders = "content-type;host;x-tc-action";  //        String payload = "{\"Limit\": 1, \"Filters\": [{\"Values\": [\"\\u672a\\u547d\\u540d\"], \"Name\": \"instance-name\"}]}";         String hashedRequestPayload = sha256Hex(payload);         String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;         System.out.println(canonicalRequest);          // ************* 步骤 2:拼接待签名字符串 *************         String credentialScope = date + "/" + service + "/" + "tc3_request";         String hashedCanonicalRequest = sha256Hex(canonicalRequest);         String stringToSign = algorithm + "\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;         System.out.println(stringToSign);          // ************* 步骤 3:计算签名 *************         byte[] secretDate = hmac256(("TC3" + SECRET_KEY).getBytes(UTF8), date);         byte[] secretService = hmac256(secretDate, service);         byte[] secretSigning = hmac256(secretService, "tc3_request");         String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();         System.out.println(signature);          // ************* 步骤 4:拼接 Authorization *************         String authorization = algorithm + " " + "Credential=" + SECRET_ID + "/" + credentialScope + ", " + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;         System.out.println(authorization);          HttpHeaders httpHeaders = new HttpHeaders();         httpHeaders.add("Authorization", authorization);         httpHeaders.add("Content-Type", CT_JSON);         httpHeaders.add("Host", host);         httpHeaders.add("X-TC-Action", action);         httpHeaders.add("X-TC-Timestamp", timestamp);         httpHeaders.add("X-TC-Version", version);         httpHeaders.add("X-TC-Region", region);          StringBuilder sb = new StringBuilder();         sb.append("curl -X POST https://").append(host).append(" -H \"Authorization: ").append(authorization).append("\"").append(" -H \"Content-Type: application/json; charset=utf-8\"").append(" -H \"Host: ").append(host).append("\"").append(" -H \"X-TC-Action: ").append(action).append("\"").append(" -H \"X-TC-Timestamp: ").append(timestamp).append("\"").append(" -H \"X-TC-Version: ").append(version).append("\"").append(" -H \"X-TC-Region: ").append(region).append("\"").append(" -d '").append(payload).append("'");         System.out.println(sb.toString());          return httpHeaders;     } } 

调用

     HttpHeaders headers = tencentCloudAPITC3Demo.buildHeader(req);             ResponseEntity<String> stringResponseEntity = restTemplateUtils.serviceApiInvoke(req, tencentOcrUrl, headers);
    public ResponseEntity<String> serviceApiInvoke(String requestBody, String url, HttpHeaders headers) {         // 创建 HttpEntity 对象,用于设置请求体和请求头         HttpEntity<String> httpEntity = new HttpEntity<>(requestBody, headers);         // 发送 POST 请求并获取响应         ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);         // 输出响应结果         return response;     }

响应乱码问题

方案1

    public ResponseEntity<String> serviceApiInvoke(String requestBody, String url, HttpHeaders headers) {         // 创建 HttpEntity 对象,用于设置请求体和请求头         HttpEntity<String> httpEntity = new HttpEntity<>(requestBody, headers);         List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();         for (HttpMessageConverter<?> messageConverter : messageConverters) {             if (messageConverter instanceof StringHttpMessageConverter) {                 ((StringHttpMessageConverter) messageConverter).setDefaultCharset(Charset.forName("UTF-8"));             }         }         // 发送 POST 请求并获取响应         ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);         // 输出响应结果         return response;     }

方案2

    public String serviceApiInvokeUtf8(String requestBody, String url, HttpHeaders headers) { //        HttpHeaders httpHeaders = new HttpHeaders();         // 可以设置一些参数         HttpEntity httpEntity = new HttpEntity(requestBody,headers);         ResponseEntity<byte[]> exchange = restTemplate.exchange(url, HttpMethod.POST, httpEntity, byte[].class);         try {             String result = new String(exchange.getBody(), "UTF-8");             return result;         } catch (UnsupportedEncodingException e) {             e.printStackTrace();         }         return null;     }

二,签名算法-自定义

据说也是copy官网

1,签名失败问题

背景,生产上已经跑了很长一段时间,突然有一天接口突然调不通了(什么都没动的情况下,很奇异),报错如下

2,响应报错信息

签名失败

AuthFailure.SignatureFailure

{     "body": "{\"Response\":{\"Error\":{\"Code\":\"AuthFailure.SignatureFailure\",\"Message\":\"请æ±ç­¾åéªè¯å¤±è´¥ï¼è¯·æ£æ¥æ¨çç­¾å计ç®æ¯å¦æ­£ç¡®ã\"},\"RequestId\":\"ebcf25f4-ee15-4286-8366-7352414e69e4\"}}",     "headers": {         "Date": [             "Thu, 01 Aug 2024 01:29:49 GMT"         ],         "Content-Type": [             "application/json"         ],         "Content-Length": [             "195"         ],         "Connection": [             "keep-alive"         ]     },     "statusCode": 4,     "statusCodeValue": 200 }

3,算法代码

package com.smcv.customer.service.util;  import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders;  import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone;   @Slf4j public class PdfUtils {  //    FailedOperation.DownLoadError	文件下载失败。 //    FailedOperation.ImageDecodeFailed	图片解码失败。 //    FailedOperation.OcrFailed	OCR识别失败。 //    FailedOperation.UnKnowError	未知错误。 //    FailedOperation.UnOpenError	服务未开通。 //    InvalidParameterValue.InvalidParameterValueLimit	参数值错误。 //    LimitExceeded.TooLargeFileError	文件内容太大。 //    ResourcesSoldOut.ChargeStatusException	计费状态异常      private final static Charset UTF8 = StandardCharsets.UTF_8;      // 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKIDz8krbsJ5**********mLPx3EXAMPL     private final static String SECRET_ID = "";     // 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 Gu5t9xGAR***********EXAMPLE     private final static String SECRET_KEY = "";      private final static String CT_JSON = "application/json";      public static byte[] hmac256(byte[] key, String msg) throws Exception {         Mac mac = Mac.getInstance("HmacSHA256");         SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());         mac.init(secretKeySpec);         return mac.doFinal(msg.getBytes(UTF8));     }       public static String sha256Hex(String s) throws Exception {         MessageDigest md = MessageDigest.getInstance("SHA-256");         byte[] d = md.digest(s.getBytes(UTF8));         return DatatypeConverter.printHexBinary(d).toLowerCase();     }       public static HttpHeaders getTncOrc(String payload) throws Exception {         String service = "ocr";         String host = "ocr.tencentcloudapi.com";         String region = "ap-shanghai";         String action = "SmartStructuralOCRV2";         String tag = "cdf41db8-29e9-11ee-9ed1-5254005e545b";         String version = "2018-11-19";         String algorithm = "TC3-HMAC-SHA256";         String timestamp = String.valueOf(System.currentTimeMillis() / 1000);         //String timestamp = "1689760798";         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");         // 注意时区,否则容易出错         sdf.setTimeZone(TimeZone.getTimeZone("UTC"));         String date = sdf.format(new Date(Long.parseLong(timestamp + "000")));           // ************* 步骤 1:拼接规范请求串 *************         String httpRequestMethod = "POST";         String canonicalUri = "/";         String canonicalQueryString = "";         String canonicalHeaders = "content-type:application/json\n" + "host:" + host + "\n" + "x-tc-action:" + action.toLowerCase() + "\n";         String signedHeaders = "content-type;host;x-tc-action";           String hashedRequestPayload = sha256Hex(payload);         String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n"                 + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;           // ************* 步骤 2:拼接待签名字符串 *************         String credentialScope = date + "/" + service + "/" + "tc3_request";         String hashedCanonicalRequest = sha256Hex(canonicalRequest);         String stringToSign = algorithm + "\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;          // ************* 步骤 3:计算签名 *************         byte[] secretDate = hmac256(("TC3" + SECRET_KEY).getBytes(UTF8), date);         byte[] secretService = hmac256(secretDate, service);         byte[] secretSigning = hmac256(secretService, "tc3_request");         String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();          // ************* 步骤 4:拼接 Authorization *************         String authorization = algorithm + " " + "Credential=" + SECRET_ID + "/" + credentialScope + ", "                 + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;          HttpHeaders headers = new HttpHeaders();         headers.add("Authorization", authorization);         headers.add("Content-Type", CT_JSON);         headers.add("Host", host);         headers.add("X-TC-Action", action);         headers.add("X-TC-Timestamp", timestamp);         headers.add("X-TC-Version", version);         headers.add("X-TC-Region", region);         headers.add("X-TC-Language", "zh-CN");  // //        StringBuilder sb = new StringBuilder(); //        sb.append("curl -X POST https://").append(host) //                .append(" -H \"Authorization: ").append(authorization).append("\"") //                .append(" -H \"Content-Type: ").append(CT_JSON).append("\"") //                .append(" -H \"Host: ").append(host).append("\"") //                .append(" -H \"X-TC-Action: ").append(action).append("\"") //                .append(" -H \"X-TC-Timestamp: ").append(timestamp).append("\"") //                .append(" -H \"X-TC-Version: ").append(version).append("\"") //                .append(" -H \"X-TC-Region: ").append(region).append("\"") //                .append(" -H \"X-TC-Language: ").append("zh-CN").append("\"") //                .append(" -d '").append(payload).append("'"); //        log.info(sb.toString());           return headers;      }   } 

4,原因

对比官网签名算法,主要区别在于编码方式

处理方案:替换以下内容,接口正常了。改回老的还是签名失败(交叉对比确认,肯定是签名失败了)

private final static String CT_JSON = "application/json"; 
private final static String CT_JSON = "application/json; charset=utf-8"; 
String canonicalHeaders = "content-type:application/json\n" + "host:" + host + "\n" + "x-tc-action:" + action.toLowerCase() + "\n"; 
String canonicalHeaders = "content-type:application/json; charset=utf-8\n" + "host:" + host + "\n" + "x-tc-action:" + action.toLowerCase() + "\n";

5,又突然好了 

上面第四点还是用老的,不写charset=utf-8,tmd接口又正常了,why?不知道!

三,签名算法-腾讯运维提供

调用

String req = JSON.toJSONString(tncOrcReqDTO); HashMap<String, String> authorizationHearderV3 = SingtrueUtil.getAuthorizationHearderV3(req); String bizTokenKey = SingtrueUtil.getBizTokenKey(authorizationHearderV3, req);

算法

package com.smcv.customer.service.util;  import org.springframework.http.HttpHeaders;  import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.TimeZone;  import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec;  public class SingtrueUtil {      private static final String TAG = "SigtrueUtil";     private final static String ALGORITHM = "TC3-HMAC-SHA256"; // TC3-HMAC-SHA256:签名方法,目前固定取该值;      private static final Charset UTF8 = StandardCharsets.UTF_8;     private final static String CT_JSON = "application/json; charset=utf-8";      private static String action = "SmartStructuralOCRV2";     private static String urlStr = "https://ocr.tencentcloudapi.com";     private static String service = "ocr";     private static String version = "2018-11-19";     private static String region = "ap-shanghai";     private static String tempToken = null;     private final static String host = "ocr.tencentcloudapi.com";     private final static String secretId = "";     private final static String secretKey = "";      /**      * 腾讯云签名      *      * @param bodyParam body参数      * @param service   服务名      * @param secretId  secretId      * @param secretKey secretKey      * @param tempToken 临时证书所用的 Token ,需要结合临时密钥一起使用。临时密钥和 Token      *                  需要到访问管理服务调用接口获取。长期密钥不需要 Token。      * @param action    接口名称      * @param version   版本号      * @param region    区域      * @return headers 请求头      * @throws Exception e      */     public static HashMap<String, String> getAuthorizationHearder(             String host,             String bodyParam,             String service,             String secretId,             String secretKey,             String tempToken,             String action,             String version,             String region) throws Exception {         String timestamp = String.valueOf(System.currentTimeMillis() / 1000);// 当前 UNIX 时间戳,可记录发起 API         // 请求的时间。注意:如果与服务器时间相差超过5分钟,会引起签名过期错误         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");         // 注意时区,否则容易出错         sdf.setTimeZone(TimeZone.getTimeZone("UTC"));         String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));          // ************* 步骤 1:拼接规范请求串 *************         String httpRequestMethod = "POST";         String canonicalUri = "/";         String canonicalQueryString = "";         String canonicalHeaders = "content-type:application/json; charset=utf-8\n" + "host:" + host + "\n";         String signedHeaders = "content-type;host";          String hashedRequestPayload = sha256Hex(bodyParam);         String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n"                 + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;         System.out.println(canonicalRequest);          // ************* 步骤 2:拼接待签名字符串 *************         String credentialScope = date + "/" + service + "/" + "tc3_request";         String hashedCanonicalRequest = sha256Hex(canonicalRequest);         String stringToSign = ALGORITHM + "\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;         System.out.println(stringToSign);          // ************* 步骤 3:计算签名 *************         byte[] secretDate = hmac256(("TC3" + secretKey).getBytes(UTF8), date);         byte[] secretService = hmac256(secretDate, service);         byte[] secretSigning = hmac256(secretService, "tc3_request");         String signature = bytesToHexFun(hmac256(secretSigning, stringToSign));// DatatypeConverter.printHexBinary(hmac256(secretSigning,         // stringToSign)).toLowerCase();         System.out.println(signature);          // ************* 步骤 4:拼接 Authorization *************         String authorization = ALGORITHM + " " + "Credential=" + secretId + "/" + credentialScope + ", "                 + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;         System.out.println(authorization);          HashMap<String, String> headers = new HashMap<>();         if (tempToken != null && !tempToken.isEmpty()) {             headers.put("X-TC-Token", tempToken);         }         headers.put("Authorization", authorization);         headers.put("Content-Type", CT_JSON);         headers.put("Host", host);         headers.put("X-TC-Action", action);         headers.put("X-TC-Timestamp", timestamp);         headers.put("X-TC-Version", version);         headers.put("X-TC-Region", region);          StringBuilder sb = new StringBuilder();         sb.append("curl -X POST https://").append(host).append(" -H \"Authorization: ").append(authorization)                 .append("\"").append(" -H \"Content-Type: application/json; charset=utf-8\"").append(" -H \"Host: ")                 .append(host).append("\"").append(" -H \"X-TC-Action: ").append(action).append("\"")                 .append(" -H \"X-TC-Timestamp: ").append(timestamp).append("\"").append(" -H \"X-TC-Version: ")                 .append(version).append("\"").append(" -H \"X-TC-Region: ").append(region).append("\"").append(" -d '")                 .append(bodyParam).append("'");         System.out.println(sb);         return headers;     }      public static HashMap<String, String> getAuthorizationHearderV3(String bodyParam) throws Exception {         String timestamp = String.valueOf(System.currentTimeMillis() / 1000);// 当前 UNIX 时间戳,可记录发起 API         // 请求的时间。注意:如果与服务器时间相差超过5分钟,会引起签名过期错误         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");         // 注意时区,否则容易出错         sdf.setTimeZone(TimeZone.getTimeZone("UTC"));         String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));          // ************* 步骤 1:拼接规范请求串 *************         String httpRequestMethod = "POST";         String canonicalUri = "/";         String canonicalQueryString = "";         String canonicalHeaders = "content-type:application/json; charset=utf-8\n" + "host:" + host + "\n";         String signedHeaders = "content-type;host";          String hashedRequestPayload = sha256Hex(bodyParam);         String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n"                 + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;         System.out.println(canonicalRequest);          // ************* 步骤 2:拼接待签名字符串 *************         String credentialScope = date + "/" + service + "/" + "tc3_request";         String hashedCanonicalRequest = sha256Hex(canonicalRequest);         String stringToSign = ALGORITHM + "\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;         System.out.println(stringToSign);          // ************* 步骤 3:计算签名 *************         byte[] secretDate = hmac256(("TC3" + secretKey).getBytes(UTF8), date);         byte[] secretService = hmac256(secretDate, service);         byte[] secretSigning = hmac256(secretService, "tc3_request");         String signature = bytesToHexFun(hmac256(secretSigning, stringToSign));// DatatypeConverter.printHexBinary(hmac256(secretSigning,         // stringToSign)).toLowerCase();         System.out.println(signature);          // ************* 步骤 4:拼接 Authorization *************         String authorization = ALGORITHM + " " + "Credential=" + secretId + "/" + credentialScope + ", "                 + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;         System.out.println(authorization);          HashMap<String, String> headers = new HashMap<>();         if (tempToken != null && !tempToken.isEmpty()) {             headers.put("X-TC-Token", tempToken);         }         headers.put("Authorization", authorization);         headers.put("Content-Type", CT_JSON);         headers.put("Host", host);         headers.put("X-TC-Action", action);         headers.put("X-TC-Timestamp", timestamp);         headers.put("X-TC-Version", version);         headers.put("X-TC-Region", region);         ;  //		StringBuilder sb = new StringBuilder(); //		sb.append("curl -X POST https://").append(host).append(" -H \"Authorization: ").append(authorization) //				.append("\"").append(" -H \"Content-Type: application/json; charset=utf-8\"").append(" -H \"Host: ") //				.append(host).append("\"").append(" -H \"X-TC-Action: ").append(action).append("\"") //				.append(" -H \"X-TC-Timestamp: ").append(timestamp).append("\"").append(" -H \"X-TC-Version: ") //				.append(version).append("\"").append(" -H \"X-TC-Region: ").append(region).append("\"").append(" -d '") //				.append(bodyParam).append("'"); //		System.out.println(sb);         return headers;     }      public static HttpHeaders getAuthorizationHearderV2(String bodyParam) throws Exception {         String timestamp = String.valueOf(System.currentTimeMillis() / 1000);// 当前 UNIX 时间戳,可记录发起 API         // 请求的时间。注意:如果与服务器时间相差超过5分钟,会引起签名过期错误         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");         // 注意时区,否则容易出错         sdf.setTimeZone(TimeZone.getTimeZone("UTC"));         String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));          // ************* 步骤 1:拼接规范请求串 *************         String httpRequestMethod = "POST";         String canonicalUri = "/";         String canonicalQueryString = "";         String canonicalHeaders = "content-type:application/json; charset=utf-8\n" + "host:" + host + "\n";         String signedHeaders = "content-type;host";          String hashedRequestPayload = sha256Hex(bodyParam);         String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n"                 + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;         System.out.println(canonicalRequest);          // ************* 步骤 2:拼接待签名字符串 *************         String credentialScope = date + "/" + service + "/" + "tc3_request";         String hashedCanonicalRequest = sha256Hex(canonicalRequest);         String stringToSign = ALGORITHM + "\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;         System.out.println(stringToSign);          // ************* 步骤 3:计算签名 *************         byte[] secretDate = hmac256(("TC3" + secretKey).getBytes(UTF8), date);         byte[] secretService = hmac256(secretDate, service);         byte[] secretSigning = hmac256(secretService, "tc3_request");         String signature = bytesToHexFun(hmac256(secretSigning, stringToSign));// DatatypeConverter.printHexBinary(hmac256(secretSigning,         // stringToSign)).toLowerCase();         System.out.println(signature);          // ************* 步骤 4:拼接 Authorization *************         String authorization = ALGORITHM + " " + "Credential=" + secretId + "/" + credentialScope + ", "                 + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;         System.out.println(authorization);          HttpHeaders headers = new HttpHeaders();         headers.add("Authorization", authorization);         headers.add("Content-Type", CT_JSON);         headers.add("Host", host);         headers.add("X-TC-Action", action);         headers.add("X-TC-Timestamp", timestamp);         headers.add("X-TC-Version", version);         headers.add("X-TC-Region", region);         headers.add("X-TC-Language", "zh-CN");  //		StringBuilder sb = new StringBuilder(); //		sb.append("curl -X POST https://").append(host).append(" -H \"Authorization: ").append(authorization) //				.append("\"").append(" -H \"Content-Type: application/json; charset=utf-8\"").append(" -H \"Host: ") //				.append(host).append("\"").append(" -H \"X-TC-Action: ").append(action).append("\"") //				.append(" -H \"X-TC-Timestamp: ").append(timestamp).append("\"").append(" -H \"X-TC-Version: ") //				.append(version).append("\"").append(" -H \"X-TC-Region: ").append(region).append("\"").append(" -d '") //				.append(bodyParam).append("'"); //		System.out.println(sb);         return headers;     }      public static String getBizTokenKey(HashMap<String, String> headerMap, String bodyParam) throws IOException {         String resultString;         HttpURLConnection httpURLConnection = null;         try {             URL url = new URL(urlStr);             httpURLConnection = (HttpURLConnection) url.openConnection();             httpURLConnection.setConnectTimeout(6000);             httpURLConnection.setUseCaches(false);// 不使用缓存             httpURLConnection.setInstanceFollowRedirects(true);// 是成员变量 仅作用域当前函数,设置当前这个对象             httpURLConnection.setReadTimeout(3000);             httpURLConnection.setDoInput(true);             httpURLConnection.setDoOutput(true);             httpURLConnection.setRequestMethod("POST");             for (Map.Entry<String, String> entry : headerMap.entrySet()) {                 httpURLConnection.setRequestProperty(entry.getKey(), entry.getValue());             }             // httpURLConnection.setRequestProperty();             httpURLConnection.connect();             // ---------------使用字节流发送数据---------------------------             OutputStream out = httpURLConnection.getOutputStream();             // 缓冲字节流 包装字节流             BufferedOutputStream bos = new BufferedOutputStream(out);             // 把字节流数组写入缓冲区中             bos.write(bodyParam.getBytes("UTF-8"));             // 刷新缓冲区 发送数据             bos.flush();             out.close();             bos.close();             // 如果响应码为200代表请求访问成功             if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {                 InputStream in = httpURLConnection.getInputStream();                 resultString = getContent(in);             } else {                 throw new RuntimeException("请求失败");             }         } catch (IOException e) {             e.printStackTrace();             throw new RuntimeException("请求失败");         } finally {             if (httpURLConnection != null) {                 httpURLConnection.disconnect();             }         }         return resultString;     }      /**      * inputStream转为String类型      *      * @param inputStream      * @return      */     private static String getContent(InputStream inputStream) {         BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));         StringBuilder sb = new StringBuilder();         String line = null;         try {             while ((line = bufferedReader.readLine()) != null) {                 sb.append(line + "/n");             }         } catch (IOException e) {             e.printStackTrace();         } finally {             try {                 inputStream.close();             } catch (IOException e) {                 e.printStackTrace();             }         }         return sb.toString().replace("/n", "");     }      private static byte[] hmac256(byte[] key, String msg) throws Exception {         Mac mac = Mac.getInstance("HmacSHA256");         SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());         mac.init(secretKeySpec);         return mac.doFinal(msg.getBytes(UTF8));     }      private static String sha256Hex(String s) throws Exception {         MessageDigest md = MessageDigest.getInstance("SHA-256");         byte[] d = md.digest(s.getBytes(UTF8));         return bytesToHexFun(d);// DatatypeConverter.printHexBinary(d).toLowerCase();     }      private static String bytesToHexFun(byte[] bytes) {         StringBuilder buf = new StringBuilder(bytes.length * 2);         for (byte b : bytes) { // 使用String的format方法进行转换             buf.append(String.format("%02x", b & 0xff));         }         return buf.toString();     } } 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!