Signature
Every TSDB API request requires a signature for authentication, regardless of whether the request uses HTTP or HTTPS. The signature is computed from your AccessKey ID and AccessKey secret using HMAC-SHA1.
If you use an Alibaba Cloud SDK, the SDK handles request signing automatically. Read this page only if you are making direct API calls without an SDK or implementing a custom client.
How it works
Signing a request involves three high-level steps:
Build a canonicalized query string from the sorted, URL-encoded request parameters.
Construct a
StringToSignfrom the HTTP method, a percent-encoded slash, and the encoded canonicalized query string.Compute an HMAC-SHA1 hash of
StringToSignusing your AccessKey secret, Base64-encode the result, and append it to the request as theSignatureparameter.
TSDB then replicates this process on the server side and grants access only when the signatures match.
Prerequisites
Before you begin, ensure that you have:
An AccessKey ID and AccessKey secret — obtain and manage these on the Alibaba Cloud console
Familiarity with HMAC-SHA1 (RFC 2104) and Base64 encoding
Sign a request
Step 1: Build the canonicalized query string
1.1 Sort the parameters
Collect all public request parameters and your API-specific parameters. Sort them alphabetically by parameter name. Exclude the Signature parameter itself.
For GET requests, these parameters form the query string — the portion of the URI after ?, with pairs joined by &.
1.2 URL-encode the names and values
Encode each parameter name and value using UTF-8 percent-encoding. Apply these rules:
Leave unencoded: letters A–Z and a–z, digits 0–9, and the characters
-,_,.,~Encode everything else as
%XY, where XY is the uppercase hex value of the ASCII code — for example,"becomes%22Encode extended UTF-8 characters as
%XY%ZA…Encode spaces as
%20, not+
Standard URL-encoding libraries such as Java's java.net.URLEncoder follow the application/x-www-form-urlencoded MIME type, which differs from the rules above. After encoding, replace + with %20, * with %2A, and change %7E back to ~.
1.3 Join each name–value pair with =
Connect each encoded parameter name to its encoded value with an equal sign.
1.4 Join all pairs with &
Sort the name=value pairs alphabetically, then join them with & to form the canonicalized query string.
Step 2: Construct the StringToSign
Use this format:
StringToSign =
HTTPMethod + "&" +
percentEncode("/") + "&" +
percentEncode(CanonicalizedQueryString)| Component | Value |
|---|---|
HTTPMethod | The HTTP method for the request, for example GET |
percentEncode("/") | The percent-encoded slash — always %2F |
percentEncode(CanonicalizedQueryString) | The canonicalized query string from step 1, encoded again using the rules in step 1.2 |
Step 3: Compute the HMAC-SHA1 signature
Compute the HMAC value of StringToSign using RFC 2104 and SHA1. The signing key is your AccessKey secret followed by & (ASCII 38):
Key = AccessKey secret + "&"Step 4: Base64-encode the HMAC value
Base64-encode the HMAC value from step 3. The result is your signature.
Step 5: Append the signature to the request
Add the signature as the Signature parameter. URL-encode the signature value per RFC 3986 before appending it, the same as any other parameter value.
Sample
This section walks through signing a DescribeHiTSDBInstanceList request. The output at each step lets you verify your own implementation against known values.
Starting parameters (before signing):
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-01StringToSign (after sorting, URL-encoding, and applying the formula from step 2):
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-01HMAC-SHA1 key and computed signature:
| Value | Content |
|---|---|
| AccessKey ID | testid |
| AccessKey secret | testsecret |
| HMAC key | testsecret& |
| Computed signature | h/ka/jNO+WZv8Tqgo4a75sp6eTs= |
Final signed request URL (with Signature appended and URL-encoded):
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%3DJava sample code
The following Java example constructs and signs a DescribeHiTSDBInstanceList request. All signing steps described above correspond directly to the annotated sections in the code.
public static void hitsdbOpenAPI() throws NoSuchAlgorithmException, InvalidKeyException, IOException {
// Step 1: Set credentials
String accessKey = "testid";
String accessSecret = "testsecret";
// Step 1.1: Collect and sort parameters alphabetically using TreeMap
Map<String, String> parameters = new TreeMap<String, String>();
parameters.put("Format", "JSON");
parameters.put("Action", "DescribeHiTSDBInstanceList");
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");
// Steps 1.2-1.4: URL-encode names and values, then join with = and &
StringBuilder paramStr = new StringBuilder();
for (Map.Entry<String, String> entry : parameters.entrySet()) {
paramStr.append(percentEncode(entry.getKey()))
.append("=")
.append(percentEncode(entry.getValue()))
.append("&");
}
paramStr.deleteCharAt(paramStr.length() - 1);
// Step 2: Construct StringToSign
StringBuilder stringToSign = new StringBuilder();
stringToSign.append("GET").append("&")
.append(percentEncode("/")).append("&")
.append(percentEncode(paramStr.toString()));
// Step 3: Compute HMAC-SHA1 - key is AccessKey secret + "&"
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec((accessSecret + "&").getBytes("UTF-8"), "HmacSHA1"));
byte[] signData = mac.doFinal(stringToSign.toString().getBytes("UTF-8"));
// Step 4: Base64-encode the HMAC value
String signStr = Base64Helper.encode(signData);
// Step 5: Append URL-encoded signature to the request URL
String requestUrl = "http://hitsdb.aliyuncs.com/?" + paramStr.toString()
+ "&Signature=" + percentEncode(signStr);
// Send the HTTP GET 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()));
}
// URL-encode a value according to the rules in step 1.2
public static String percentEncode(String value) throws UnsupportedEncodingException {
return value != null ? URLEncoder.encode(value, "UTF-8")
.replace("+", "%20")
.replace("*", "%2A")
.replace("%7E", "~") : null;
}
// Return the current time in ISO 8601 format (UTC)
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());
}Replace testid and testsecret with your actual AccessKey ID and AccessKey secret. Store credentials in environment variables rather than hardcoding them in source code.