You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by GitBox <gi...@apache.org> on 2022/01/13 06:33:17 UTC

[GitHub] [apisix] kennethToyuan commented on issue #6080: hmac-auth plugins,java hmac-sha256 signature check fail

kennethToyuan commented on issue #6080:
URL: https://github.com/apache/apisix/issues/6080#issuecomment-1011837448


   > 你可以使用这个代码: `import javafx.util.Pair; 导入 lmport javafx.util.Pair; 导入 lombok.extern.slf4j.Slf4j;
   > 
   > 导入 javax.crypto.Mac; 导入 javax.crypto.spec.SecretKeySpec; 导入 javax.xml.bind.DatatypeConverter; 导入 java.io.UnsupportedEncodingException; 导入 java.net.URI; 导入 java.net.URL; 导入 java.net.URLEncoder; 导入 java.text.DateFormat; 导入 java.text.SimpleDateFormat; 导入java.util.*;ombok.extern.slf4j.Slf4j;
   > 
   > 导入 javax.crypto.Mac; 导入 javax.crypto.spec.SecretKeySpec; 导入 javax.xml.bind.DatatypeConverter; 导入 java.io.UnsupportedEncodingException; 导入 java.net.URI; 导入 java.net.URL; 导入 java.net.URLEncoder; 导入 java.text.DateFormat; 导入 java.text.SimpleDateFormat; 导入 java.util.*; 导入 java.util.stream.Collectors;
   > 
   > @slf4j 公共类 HmacAuthUtil {
   > 
   > ```
   > /**
   >  * 构造请求 header
   >  * @param urlStr 请求url,全路径格式,比如:https://xx.xx.xx.cn/api/p/v1/user.get
   >  * @param requestMethod 请求方法,大写格式,如:GET, POST
   >  * @param accessKey 
   >  * @param secretKey 
   >  * @return
   >  */
   > public static Map<String, String> generateHeader(String urlStr,String requestMethod, String accessKey, String secretKey) {
   >     log.info("params,urlStr={},requestMethod={},accessKey={},secretKey={}",urlStr,requestMethod,accessKey,secretKey);
   >     Map<String, String> header = new HashMap<>();
   >     try {
   >         DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
   >         dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
   >         String date = dateFormat.format(new Date());
   >         URL url = new URL(urlStr);
   >         URI uri = new URI(url.getProtocol(), url.getHost(), url.getPath(), url.getQuery(), null);
   > 
   >         String canonicalQueryString = getCanonicalQueryString(uri.getQuery());
   > 
   >         String message = requestMethod.toUpperCase() + "\n" + uri.getPath() + "\n" + canonicalQueryString + "\n"  + accessKey + "\n" + date + "\n";
   > 
   >         Mac hasher = Mac.getInstance("HmacSHA256");
   >         hasher.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"));
   > 
   >         byte[] hash = hasher.doFinal(message.getBytes());
   > 
   >         // to lowercase hexits
   >         DatatypeConverter.printHexBinary(hash);
   > 
   >         // to base64
   >         String sign = DatatypeConverter.printBase64Binary(hash);
   >         header.put("X-HMAC-SIGNATURE", sign);
   >         header.put("X-HMAC-ALGORITHM", "hmac-sha256");
   >         header.put("X-HMAC-ACCESS-KEY", accessKey);
   >         header.put("Date", date);
   >     } catch (Exception e) {
   >         log.error("generate error",e);
   >         throw new RuntimeException("generate header error");
   >     }
   >     log.info("header info,{}",header);
   >     return header;
   > }
   > 
   > private static String getCanonicalQueryString(String query) {
   >     if (query == null || query.trim().length() == 0) {
   >         return "";
   >     }
   >     List<Pair<String, String>> queryParamList = new ArrayList<>();
   >     String[] params = query.split("&");
   >     for (String param : params) {
   >         int eqIndex = param.indexOf("=");
   >         String key = param.substring(0, eqIndex);
   >         String value = param.substring(eqIndex+1);
   >         Pair<String, String> pair = new Pair<String, String>(key,value);
   >         queryParamList.add(pair);
   >     }
   > 
   >     List<Pair<String, String>> sortedParamList = queryParamList.stream().sorted(Comparator.comparing(param -> param.getKey() + "=" + Optional.ofNullable(param.getValue()).orElse(""))).collect(Collectors.toList());
   >     List<Pair<String, String>> encodeParamList = new ArrayList<>();
   >     sortedParamList.stream().forEach(param -> {
   >         try {
   >             String key = URLEncoder.encode(param.getKey(), "utf-8");
   >             String value = URLEncoder.encode(Optional.ofNullable(param.getValue()).orElse(""), "utf-8")
   >                     .replaceAll("\\%2B","%20")
   >                     .replaceAll("\\+","%20")
   >                     .replaceAll("\\%21","!")
   >                     .replaceAll("\\%27","'")
   >                     .replaceAll("\\%28","(")
   >                     .replaceAll("\\%29",")")
   >                     .replaceAll("\\%7E","~")
   >                     .replaceAll("\\%25","%")
   >                     ;
   >             encodeParamList.add(new Pair<>(key, value));
   >         } catch (UnsupportedEncodingException e) {
   >             throw new RuntimeException("encoding error");
   >         }
   >     });
   >     StringBuilder queryParamString = new StringBuilder(64);
   >     for (Pair<String, String> encodeParam : encodeParamList) {
   >         queryParamString.append(encodeParam.getKey()).append("=").append(Optional.ofNullable(encodeParam.getValue()).orElse(""));
   >         queryParamString.append("&");
   >     }
   > 
   >     return queryParamString.substring(0, queryParamString.length() - 1);
   > }
   > ```
   > 
   > }`
   
   The result I want to return:
   {
       "data": null,
       "code": -1,
       "msg": "Invalid digest"
   }
   
   actual return result:
   {"message":"Invalid digest"}
   
   Is there a way to handle it?
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org