To ensure secure API calls, RTC authenticates each API request by signing. Whether you use HTTP or HTTPS to submit a request, you must include signature information in the request.
Signature format
To sign a RESTful API, you must add the Authorization parameter to the request header in the following format:
Authorization:acs:AccessKeyId:Singature- acs: the abbreviation for Alibaba Cloud Service. This is a fixed field and cannot be modified.
- AccessKeyId: the AccessKey ID that is used to call the API.
- Signature: the signature generated after the request is symmetrically encrypted by using the AccessKey secret.
The signature method.
The signature algorithm follows HMAC-SHA1 specifications. The AccessSecret is used to calculate the HMAC value of the encoded and sorted request string as the signature. Request signatures include operation-specific parameters. Therefore, the signature of a request varies depending on the request parameters.
Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign)) )Procedure
- Create a string-to-sign.
The string to sign (StringToSign) is the string assembled in the API request and is used to calculate the signature. The string-to-sign must be created in the following format:
StringToSign = // HTTP Header HTTP-Verb + "\n" + Accept + "\n" + Content-MD5 + "\n" +//Specify the request body that is encrypted by using the MD5 algorithm. Content-Type + "\n" + Date + "\n" + // Alibaba Cloud protocol headers CanonicalizedHeaders + // Standardize resources CanonicalizedResourceNote- For more information about HTTP headers, see HTTP headers.
- For more information about Alibaba Cloud protocol headers, see Alibaba Cloud protocol headers.
- For more information about standardization resources, see Standardization resources.
Original request example:
POST /api/call/describeCallList?xxx=xxx HTTP/1.1 Host: vdc.cn-shenzhen.aliyuncs.com Accept: application/json Content-MD5: Content-Type: application/json Date: Thu, 22 Feb 2018 07:46:12 GMT x-acs-signature-nonce: 550e8400-e29b-41d4-a716-446655440000 x-acs-signature-method: HMAC-SHA1 x-acs-action: DescribeCallList x-acs-version: 2020-12-14Example of a canonical request StringToSign:
POST application/json application/json Thu, 22 Feb 2018 07:46:12 GMT x-acs-action:DescribeCallList x-acs-signature-nonce:550e8400-e29b-41d4-a716-446655440000 x-acs-signature-method:HMAC-SHA1 x-acs-version:2016-01-02 /api/call/describeCallList?xxx=xxx - Add the signature.
Add the calculated signature to the RequestHeader in the following format:
addHeader("Authorization", "acs " + {AccessKeyId} + ":" + {Signature})
HTTP header
To calculate a signature, you must include the following parameters and arrange them in lexicographical order. If the values do not exist, you must complete them with \n.
- Accept: the return value type required by the client. Valid values: application/json and application/xml.
- Content-MD5: the Base64-encoded 128-bit MD5 hash value of the request body.
- Content-Type: the type of the HTTP request body. The type is defined in RFC 2616.
- Date: the GMT time specified in HTTP 1.1. Example: Wed, 05: 00:00 Sep. 2012 23.
Original Header Example:
Accept: application/json
Content-MD5:
Content-Type: application/json
Date: Thu, 22 Feb 2018 07:46:12 GMTExample of post-standard headers:
application/json
application/json
Thu, 22 Feb 2018 07:46:12 GMTAlibaba Cloud protocol headers (CanonicalizedHeaders)
The Alibaba Cloud canonical header, which is a non-standard HTTP header, is a parameter that appears in a request prefixed with x-acs-. A request must contain the following parameters:
- x-acs-signature-nonce: a unique, random number used to prevent replay attacks. You must use different numbers for different requests.
- x-acs-signature-method: user signature method. Currently, HMAC-SHA1 is supported.
- x-acs-action: the name of the API.
- x-acs-version: the version number of the API.
To construct the Alibaba Cloud specification header, you need to complete the following operations:
- Converts the names of all HTTP request headers prefixed with x-acs-to lowercase letters. For example, convert X-acs-Action: DescribeCallList to x-acs-action: DescribeCallList.
- Sort all HTTP request headers that are obtained from the preceding step in alphabetical order.
- Delete all spaces on each side of the delimiter between each header and value. For example, convert x-acs-action: DescribeCallList to x-acs-action: DescribeCallList.
- Separate all headers and content with delimiters (
\n) to form the final canonicalized headers.
Original Header Example:
x-acs-signature-nonce: 550e8400-e29b-41d4-a716-446655440000
x-acs-signature-method: HMAC-SHA1
x-acs-action: DescribeCallList
x-acs-version: 2020-12-14Example of post-standard headers:
x-acs-action:DescribeCallList
x-acs-signature-nonce:550e8400-e29b-41d4-a716-446655440000
x-acs-signature-method:HMAC-SHA1
x-acs-version:2020-12-14Canonicalized resource (CanonicalizedResource)
CanonicalizedResource indicates the specification description of the resource to be accessed. You need to arrange the subresources and query parameters together by lexicographic order, and use & as the delimiter to generate the subresource string (?).
Original request example:
/api/call/describeCallList?yyy=yyy&xxx=xxxSample post-canonical request:
/api/call/describeCallList?xxx=xxx&yyy=yyySignature example
- CommonRequest mode
Currently, Data Service has not generated its own SDK. You can use CommonRequest to uniformly call (CommonRequest has already implemented a signature). The method is as follows:
- Introduce Maven dependencies.
<dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.5.6</version> </dependency> - Run the following sample code.
CommonRequest request = new CommonRequest(); request.setSysMethod(MethodType.POST); request.setSysProtocol(ProtocolType.HTTP); request.setSysDomain("vdc.cn-shenzhen.aliyuncs.com"); request.setSysVersion("2020-12-14"); request.setSysUriPattern("/api/call/describeCallList"); request.putQueryParameter("AppId", "pdtkb2qy"); request.putQueryParameter("PageNo", "1"); request.putQueryParameter("PageSize", "10"); long startTs = System.currentTimeMillis() / 1000 - 24 * 60 * 60 * 3; long endTs = System.currentTimeMillis()/1000; request.putQueryParameter("StartTs", String.valueOf(startTs)); request.putQueryParameter("EndTs", String.valueOf(endTs)); try { DefaultProfile profile = DefaultProfile.getProfile("cn-shenzhen", yourAccessKey, yourSecret); CommonResponse response = new DefaultAcsClient(profile).getCommonResponse(request); System.out.println(response.getData()); } catch (Exception e) { e.printStackTrace(); }
- Introduce Maven dependencies.
- Implement the signature method by yourself
String host = "https://vdc.cn-shenzhen.aliyuncs.com"; String action = "DescribeCallList"; String version = "2020-12-14"; long startTs = System.currentTimeMillis()/1000 - 24 * 60 * 60 * 3; long endTs = System.currentTimeMillis() / 1000; // Build custom parameters for the interface. Map<String, String> params = Maps.newTreeMap(String::compareTo); params.put("AppId", "pdtkb2qy"); params.put("StartTs", String.valueOf(startTs)); params.put("EndTs", String.valueOf(endTs)); params.put("PageNo", "1"); params.put("PageSize", "10"); // Standardize resources List<String> queryParams = Lists.newArrayList(); params.forEach((key, value) -> queryParams.add(key + "=" + value)); String canonicalizedResource = "/api/call/describeCallList?" + StringUtils.join(queryParams , "&"); // Build an Alibaba Cloud protocol header. HttpHeaders headers = new HttpHeaders(); String generateRandom = UUID.randomUUID().toString(); headers.set("x-acs-action", action); headers.set("x-acs-version", version); headers.set("x-acs-signature-nonce", generateRandom); headers.set("x-acs-signature-method", "HMAC-SHA1"); headers.set("x-acs-signature-version", "1.0"); List<String> canonicalizedHeaders = Lists.newArrayList(); headers.forEach((k, v) -> canonicalizedHeaders.add(k + ":" + v.get(0))); canonicalizedHeaders.sort(String::compareTo); String canonicalizedHeaderStr = canonicalizedHeaders.stream() .map(value -> StringUtils.trim(value) + "\n") .collect(Collectors.joining()); // Other Http protocol headers SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); String currentDate = dateFormat.format(new Date()); headers.set("Date", currentDate); MediaType accept = MediaType.APPLICATION_JSON; headers.setAccept(Collections.singletonList(accept)); MediaType contentType = MediaType.APPLICATION_JSON; headers.setContentType(contentType); // StringToSign = // HTTP-Verb + "\n" + // Accept + "\n” + // Content-MD5 + "\n" + // Content-Type + "\n" + // Date + "\n" + // CanonicalizedHeaders + CanonicalizedResource List<String> signString = Lists.newArrayList(); signString.add(HttpMethod.POST.name()); signString.add(accept.toString()); signString.add(""); signString.add(contentType.toString()); signString.add(currentDate); String stringToSign = StringUtils.join(signString, "\n") + "\n" + canonicalizedHeaderStr + canonicalizedResource; try { // Signature // Calculate the HMAC value of the string to be signed. String algorithm = "HmacSHA1"; SecretKeySpec signKey = new SecretKeySpec(yourSecret.getBytes(), algorithm); Mac mac = Mac.getInstance(algorithm); mac.init(signKey); byte[] bytes = mac.doFinal(stringToSign.getBytes()); // Encode the calculated HMAC value into a string based on Base64 encoding rules to obtain the final signature value (Signature) String sign = new BASE64Encoder().encode(bytes); String authorization = "acs " + yourAccessKey + ":" + sign; headers.set("Authorization", authorization); HttpEntity<String> entity = new HttpEntity<>(headers); String reqUrl = host + canonicalizedResource; ResponseEntity<JSONObject> exchange = new RestTemplate().exchange(reqUrl, HttpMethod.POST, entity, JSONObject.class); if (exchange.hasBody()) { System.out.println(exchange.getBody()); } } catch (Exception e) { e.printStackTrace(); }