Request signatures

更新时间:
复制 MD 格式

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

  1. 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
        CanonicalizedResource
    Note

    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-14

    Example 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
  2. 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 GMT

Example of post-standard headers:

application/json

application/json
Thu, 22 Feb 2018 07:46:12 GMT

Alibaba 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:

  1. 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.
  2. Sort all HTTP request headers that are obtained from the preceding step in alphabetical order.
  3. 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.
  4. 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-14

Example 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-14

Canonicalized 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=xxx

Sample post-canonical request:

/api/call/describeCallList?xxx=xxx&yyy=yyy

Signature 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:

    1. Introduce Maven dependencies.
      <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>aliyun-java-sdk-core</artifactId>
        <version>4.5.6</version>
      </dependency>
    2. 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();
      }
  • 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();
    }