All Products
Search
Document Center

Time Series Database:Signature

Last Updated:Mar 24, 2022

Access Key ID and Access Key Secret

  • TSDB performs authentication on each API access request. Therefore, each request, whether being sent through HTTP or HTTPS, must contain the signature consisting of an Access Key ID and an Access Key Secret.

  • The Access Key ID and Access Key Secret are officially issued to visitors by Alibaba Cloud (visitors can apply for and manage them at Alibaba Cloud’s official website). The Access Key ID indicates the identity of the visitor.

  • The Access Key Secret is the secret key used to encrypt and verify the signature string on the server. It must be kept confidential and only be available to Alibaba Cloud and the user.

Mechanism

When sending an API call, use the following method to sign the request:

  1. Construct a normalized request string (Canonicalized Query String) using the request parameter.

    1.1. The request parameters are ordered alphabetically by the parameter names (this includes the public request parameters and user-defined parameters for the given request interfaces described in this document, but not the Signature parameter mentioned in public request parameters).

    Note: For a request submitted using the GET method, these parameters constitute the parameter section of the request URI, that is, the section in the URI following the question mark (?) and connected by the ampersand (&).

    1.2. Encode the name and value of each request parameter. The names and values must be URL encoded by using the UTF-8 character set. The URL encoding rules are as follows:

    • English letters A–Z and a–z, digits 0–9, and characters “-“, “_”, “.”, and “~” are not encoded.

    • Other characters are encoded in “%XY” format, with XY representing the characters’ ASCII code in hexadecimal notation. For example, the double quotes (“) are encoded as %22.

    • Encode extended UTF-8 characters in “%XY%ZA…” format.

    • An English space ( ) is encoded as %20 rather than the plus sign (+).

      Note: Generally, libraries that support URL encoding (such as Java’s java.net.URLEncoder) are all encoded according to the rules for the “application/x-www-form-urlencoded” MIME-type. If this encoding method is used, replace the plus signs (+) in the encoded strings with %20, the asterisks (*) with %2A, and change %7E back to the tilde (~) to conform to the encoding rules described above.

    1.3. Connect the encoded parameter names and values with the equal sign (=).

    1.4. Sort the parameter name and value pairs connected by equal signs (=) in alphabetical order, and connect them with ampersands (&) to produce the canonicalized query string.

  2. Follow the following rules to construct the string used for signature calculation by using the Canonicalized Query String constructed in the previous step.

     StringToSign=
     HTTPMethod + "&" +
     percentEncode("/") + "&" +
     percentEncode(CanonicalizedQueryString)
    • HTTPMethod: indicates the HTTP method used for request submission, for example, GET.

    • percentEncode(“/”): the coded value for the character “/“ according to the URL encoding rules described in 1.2, namely, “%2F”.

    • percentEncode(CanonicalizedQueryString) indicates the encoded string of the canonicalized query string constructed in Step 1, produced by following the URL encoding rules described in 1.2.

  3. Use the preceding signature sting to calculate the signature’s HMAC value based on RFC2104 definitions.

    Note: The Key used for calculating the signature is the AccessKey Secret held by the user, added with the “&” character (ASCII:38) and is based on the SHA1 hashing.

  4. According to Base64 encoding rules, encode the preceding HMAC value, which gives you the signature value.

  5. Add the obtained signature value to the request parameters as the “Signature” parameter, which completes the request signing process.

    Note: When the obtained signature value is submitted to the HiTSDB server as the final request parameter value, the URL encoding must be performed for the value according to RFC3986 rules like other parameters.

Samples

DescribeHiTSDBInstanceList is used as an example. The request parameter string before signing is:

AccessKeyId=testid&Action=DescribeHiTSDBInstanceList&Format=JSON&RegionId=cn-hangzhou&SignatureMethod=HMAC-SHA1&SignatureNonce=ae5bdbeb-9b44-40a1-8bb4-b40784bff686&SignatureVersion=1.0&Timestamp=2016-01-20T14%3A26%3A15Z&Version=2017-06-01

Thus, the StringToSign is:

GET&%2F&AccessKeyId%3Dtestid&Action%3DDescribeHiTSDBInstanceList&Format%3DJSON&RegionId%3Dcn-hangzhou&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3Dae5bdbeb-9b44-40a1-8bb4-b40784bff686&SignatureVersion%3D1.0&Timestamp%3D2016-01-20T14%253A26%253A15Z&Version%3D2017-06-01

Assume that the Access Key ID is “testid”, the Access Key Secret is “testsecret”, and the key used for HMAC calculation is “testsecret&”. The calculated signature is:

h/ka/jNO+WZv8Tqgo4a75sp6eTs=

With the signature parameter added, the signed request URL is:

http://hitsdb.aliyuncs.com/?AccessKeyId=testid&Action=DescribeHiTSDBInstanceList&Format=JSON&RegionId=cn-hangzhou&SignatureMethod=HMAC-SHA1&SignatureNonce=ae5bdbeb-9b44-40a1-8bb4-b40784bff686&SignatureVersion=1.0&Timestamp=2016-01-20T14%3A26%3A15Z&Version=2017-06-01&Signature=h%2Fka%2FjNO%2BWZv8Tqgo4a75sp6eTs%3D

The Java sample code for calling the DescribeHiTSDBInstanceList API is as follows:

public static void hitsdbOpenAPI() throws NoSuchAlgorithmException, InvalidKeyException, IOException {
        //AccessKet and SecretKey
        String accessKey = "testid";
        String accessSecret = "testsecret";
        //Public parameters
        Map<String, String> parameters = new TreeMap<String, String>();
        parameters.put("Format", "JSON");
        parameters.put("Action", "DescribeHiTSDBInstanceList");//Calls the DescribeDrdsInstances API.
        parameters.put("Version", "2017-06-01");
        parameters.put("AccessKeyId", accessKey);
        parameters.put("SignatureMethod", "HMAC-SHA1");
        parameters.put("Timestamp", getISO8601Time());
        parameters.put("SignatureVersion", "1.0");
        parameters.put("SignatureNonce", UUID.randomUUID().toString());
        parameters.put("RegionId", "cn-hangzhou");
        StringBuilder paramStr = new StringBuilder();
        //Concatenates the request parameters.
        for(Map.Entry<String, String> entry : parameters.entrySet()) {
          paramStr.append(percentEncode(entry.getKey())).append("=").append(percentEncode(entry.getValue())).append("&");
        }
        paramStr.deleteCharAt(paramStr.length()-1);
        //Calculates the signature.
        StringBuilder stringToSign = new StringBuilder();
            stringToSign.append("GET").append("&").append(percentEncode("/"))
                  .append("&").append(percentEncode(paramStr.toString()));
            Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(new SecretKeySpec((accessSecret + "&").getBytes("UTF-8"),"HmacSHA1"));
        byte[] signData = mac.doFinal(stringToSign.toString().getBytes("UTF-8"));
        String signStr = Base64Helper.encode(signData);
        //Concatenates the URL.
        String requestUrl = "http://hitsdb.aliyuncs.com/?" + paramStr.toString() + 
            "&Signature=" +  percentEncode(signStr);
        //Ready to send the HTTP request.
        URL url = new URL(requestUrl);
        HttpURLConnection httpConn = (HttpURLConnection)url.openConnection();
        httpConn.setRequestMethod("GET");
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);
        httpConn.setUseCaches(false);
        httpConn.connect();
        InputStream content = httpConn.getInputStream();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buff = new byte[1024];
        while(true) {
           final int read = content.read(buff);
           if(read == -1) break;
           outputStream.write(buff,0,read);
        }
        System.out.println(new String(outputStream.toByteArray()));;
  }
  public static String percentEncode(String value) throws UnsupportedEncodingException{
        return value != null ? URLEncoder.encode(value, "UTF-8").replace("+", "%20")
                .replace("*", "%2A").replace("%7E", "~") : null;
    }
  static String getISO8601Time() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        df.setTimeZone(new SimpleTimeZone(0, "GMT"));
        return df.format(new Date());
  }
}