All Products
Search
Document Center

Alibaba Cloud SDK:Request syntax and signature method V3

Last Updated:May 07, 2024

This topic describes the request syntax and signature method V3. This version uses common request headers to pass the required parameters of API operations, which shields the differences between different API styles. This allows you to use the same signature method for different API styles and call Alibaba Cloud API operations in a more standard and easier way. This topic helps you understand and use the request syntax and signature method V3 of Alibaba Cloud SDKs. This topic also describes how to construct a canonicalized HTTP request and how to use a correct signature algorithm to verify the identity of a request sender. This ensures the integrity and security of the transmitted data. You can read this topic to develop Alibaba Cloud OpenAPI SDKs.

HTTP request syntax

The following table describes the components of an Alibaba Cloud API request.

Component

Required

Description

Example

Protocol

Yes

The protocol that is used to send the API request. You can read the API references of each Alibaba Cloud service to understand the protocol that is used. You can send a request over HTTP or HTTPS. To ensure data security, we recommend that you send requests over HTTPS. Valid values: https:// and http://.

https://

Endpoint

Yes

The endpoint of the Alibaba Cloud service API. API references that list the endpoints of each Alibaba Cloud service are available. You can view the endpoints of a service in different regions in these API references.

cs.aliyuncs.com

resource_URI_parameters

Yes

The identifier of the resource that you want to access.

/clusters/{cluster_id}/triggers

RequestHeader

Yes

The request headers. In most cases, information such as the API version number, hostname, and authentication information is included. For more information, see the "Request headers" section of this topic.

x-acs-action

RequestBody

Yes

The operation-specific parameters in the request body. For more information, visit OpenAPI Portal.

cluster_id

HTTPMethod

Yes

The HTTP method that is used to send the request. Valid values: PUT, POST, GET, and DELETE.

POST

Request headers

The following table describes the request headers of an Alibaba Cloud API request.

Header

Type

Required

Description

Example

x-acs-action

String

Yes

The operation that you want to perform. You can search for the API operation that you want to call in OpenAPI Portal.

RunInstances

x-acs-version

String

Yes

The version number of the API. You can view the API version of the service that you want to access in OpenAPI Portal.

2014-05-26

Authorization

String

Yes if the request is non-anonymous

The authentication information that is used to verify the validity of the request. Format: Authorization: SignatureAlgorithm Credential=AccessKeyId,SignedHeaders=SignedHeaders,Signature=Signature. SignatureAlgorithm: the encryption method of the signature string. Set the value to ACS3-HMAC-SHA256.

Credential: the AccessKey ID that is provided by Alibaba Cloud. You can view your AccessKey ID in the Resource Access Management (RAM) console. For more information about how to create an AccessKey pair, see Obtain an AccessKey pair. SignedHeaders: the names of the request headers that are used for signature calculation. Note: All common request headers except the Authorization header must be used for signature calculation.

Signature: the signature string of the request. For more information, see the "Signature method" section of this topic.

ACS3-HMAC-SHA256 Credential=YourAccessKeyId,SignedHeaders=host;x-acs-action;x-acs-content-sha256;x-acs-date;x-acs-signature-nonce;x-acs-version,Signature=e521358f7776c97df52e6b2891a8bc73026794a071b50c3323388c4e0df64804

x-acs-signature-nonce

String

No

A unique and random number that is used to prevent replay attacks. We recommend that you use different numbers for different requests.

d410180a5abf7fe235dd9b74aca91fc0

x-acs-date

String

Yes

The timestamp of the request. Specify the time in the ISO 8601 standard in the yyyy-MM-ddTHH:mm:ssZ format. The timestamp must be in UTC. Example: 2018-01-01T12:00:00Z. The timestamp must be within 15 minutes before the request is sent.

2023-10-26T09:01:01Z

host

String

Yes

The endpoint of the Alibaba Cloud service API. For more information, see the HTTP request syntax section of this topic.

ecs.cn-shanghai.aliyuncs.com

x-acs-content-sha256

String

Yes

The hash value of the request body. The hash value is encoded in Base16. The value of this header is the same as that of the HashedRequestPayload parameter.

e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

x-acs-security-token

String

Yes if Security Token Service (STS) is used for authentication

The STS token. Set this header to the value of the SecurityToken parameter in the response of the Assumerole operation.

API request construction

A complete API request consists of the following parts:

HTTPMethod /resource_URI_parameters
RequestHeader
RequestBody

Request parameters consist of common request headers and operation-specific parameters. The common request headers contain information such as the API version number and authentication information.

  • HTTPMethod: the HTTP method that is used to send the request. Valid values: PUT, POST, GET, and DELETE. For more information, see the HTTP request syntax section of this topic.

  • resource_URI_parameters: the identifier of the resource that you want to access. Example: /cluster. For more information, see the HTTP request syntax section of this topic.

  • RequestHeader: the request headers. In most cases, information such as the API version number, endpoint, and authentication information is included. For more information, see the HTTP request syntax section of this topic.

  • RequestBody: the operation-specific parameters in the request body. For more information, see the HTTP request syntax section of this topic.

Sample request to call the RunInstances operation:

POST /?ImageId=win2019_1809_x64_dtc_zh-cn_40G_alibase_20230811.vhd&RegionId=cn-shanghai HTTP/1.1
Authorization: ACS3-HMAC-SHA256 Credential=YourAccessKeyId,SignedHeaders=host;x-acs-action;x-acs-content-sha256;x-acs-date;x-acs-signature-nonce;x-acs-version,Signature=e521358f7776c97df52e6b2891a8bc73026794a071b50c3323388c4e0df64804
x-acs-action: RunInstances
host: ecs.cn-shanghai.aliyuncs.com
x-acs-date: 2023-10-26T09:01:01Z
x-acs-version: 2014-05-26
x-acs-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-acs-signature-nonce: d410180a5abf7fe235dd9b74aca91fc0
user-agent: AlibabaCloud (Mac OS X; x86_64) Java/1.8.0_352-b08 tea-util/0.2.6 TeaDSL/1
accept: application/json

Encoding

Requests and responses are encoded in UTF-8.

Responses

Each response returns a unique request ID regardless of whether the request is successful. All responses are returned in a unified format. If an API call is successful, a request ID is returned. The HTTP status code is 2xx, which is not displayed in the response. Sample success response:

{
    "RequestId": "4C467B38-3910-447D-87BC-AC049166F216"/* Returned results */
}

If an API call fails, a request ID, a service node, an error code, and an error message are returned. The HTTP status code is 4xx or 5xx. Sample failure response:

{
    "code": "400", /* Error code */
    "message": "Cluster permission denied", /* Error message */
    "requestId": "A026BC61-0523-5A6D-A5F3-314A3D92FD50", /* Request ID */
    "status": 400 /* HTTP status code */
}

If an API call fails, you can troubleshoot the error on the OpenAPI problem diagnosis page in OpenAPI Portal based on the request ID that is returned. For more information about error codes, visit the Global error code and Error Codes pages. If the error persists, you can submit a ticket and provide the endpoint and request ID. For more information about the endpoint, see the HTTP request syntax section of this topic.

Signature method

You must sign all API requests to ensure security. Alibaba Cloud uses the request signature to verify the identity of the API caller. Each API request must contain a signature, regardless of whether the request is sent over HTTP or HTTPS. This section describes how to sign API requests.

For each HTTP or HTTPS request, Alibaba Cloud uses the request signature to verify the identity of the API caller. You can perform the following steps to sign a request:

Step 1: Construct a canonicalized request

To use an AccessKey pair to calculate or verify a signature, you must construct a canonicalized request. The client and API gateway must use the same request specifications so that they can obtain the same signature string for an HTTP request to complete identity verification.

Construct a canonicalized request based on the following pseudocode:

CanonicalRequest =
  HTTPRequestMethod + '\n' +    // The HTTP method in uppercase letters.
  CanonicalURI + '\n' +         // The canonicalized Uniform Resource Identifier (URI).
  CanonicalQueryString + '\n' + // The canonicalized query string.
  CanonicalHeaders + '\n' +     // The canonicalized request headers.
  SignedHeaders + '\n' +        // The request headers that are used for signature calculation.
  HashedRequestPayload			
  • HTTPRequestMethod: the HTTP method in uppercase letters, such as POST and GET.

  • Canonicalized URI

    The encoded resource path in the URL. The resource path is the part between the endpoint and the query string. The path includes the forward slash (/) that follows the endpoint but excludes the question mark (?) that precedes the query string. You must use a canonicalized URI for signature calculation. To construct a canonicalized URI, encode the strings separated by forward slashes (/) in UTF-8 based on RFC 3986. Encoding rules:

    • Letters, digits, hyphens (-), underscores (_), periods (.), and tildes (~) do not need to be encoded.

    • Other characters must be percent encoded in the %XY format. XY indicates the ASCII code of the characters in hexadecimal notation. For example, double quotation marks (") are encoded as %22.

    • Extended UTF-8 characters are encoded in the %XY%ZA… format.

    • Spaces must be encoded as %20 instead of (+). The preceding encoding scheme is similar to but slightly different from the application/x-www-form-urlencoded Multipurpose Internet Mail Extension (MIME) encoding algorithm.

      If you use java.net.URLEncoder in the Java standard library, use percentEncode to encode the strings. In the encoded strings, replace the plus sign (+) with %20, the asterisk (*) with %2A, and %7E with a tilde (~). This way, you can obtain encoded strings that match the preceding encoding rules.

    Important

    If the resource path is empty, use a forward slash (/) as the value of the CanonicalURI parameter.

  • CanonicalQueryString: the canonicalized query string. You can perform the following steps to construct the canonicalized query string:

    1. Sort the parameters in the query string by the parameter name in alphabetical order. For parameters with the same name, sort the parameters by the parameter value in alphabetical order.

    2. Encode the parameter names and values in UTF-8 based on RFC 3986. The encoding rules are the same as those used to construct the canonicalized URI.

    3. Use an equal sign (=) to concatenate the encoded name and value of each parameter. For a parameter without a value, use an empty string as the parameter value.

    4. Sort the parameters by the encoded parameter name in alphabetical order. For parameters with the same name, sort the parameters by the encoded parameter value in alphabetical order.

    5. Use ampersands (&) to concatenate the encoded parameters in the order obtained in the previous step.

    Important

    If the query string is empty, use an empty string as the canonicalized query string, which is a blank line.

  • CanonicalizedHeaders: the non-standard HTTP headers. Non-standard HTTP headers are headers whose names are prefixed with x-acs- in the request. You can perform the following steps to construct canonicalized headers:

    1. Convert the names of all headers that are used for signature calculation to lowercase letters.

    2. Remove the spaces before and after the value of a header. If a header has multiple values, remove the spaces before and after each value, sort the values in alphabetical order, and then use commas (,) to concatenate the values.

    3. Use a colon (:) to concatenate the name and value of a header obtained in the preceding steps and add a line break at the end to construct a canonicalized header.

    4. Concatenate all canonicalized headers by the lowercase header name in alphabetical order.

    5. If no headers are used for signature calculation, use an empty string as the canonicalized headers.

    Important

    All common request headers except the Authorization header must be used for signature calculation.

  • SignedHeaders: the names of the headers that are used for signature calculation. This parameter contains the same headers as those in the CanonicalHeaders parameter. You can perform the following steps to construct signed headers:

    • Convert the names of headers in the CanonicalHeaders parameter to lowercase letters.

    • Use semicolons (;) to concatenate all the headers by lowercase header name in alphabetical order. Example: content-type;host;x-acs-date.

    • Pseudocode:

      CanonicalHeaderEntry = Lowercase(HeaderName) + ':' + Trim(HeaderValue) + '\n'
      
      CanonicalHeaders = 
          CanonicalHeaderEntry0 + CanonicalHeaderEntry1 + ... + CanonicalHeaderEntryN
  • HashedRequestPayload: the hash value of the request body. The following pseudocode shows how to generate the hash value: HashedRequestPayload = HexEncode(Hash(RequestPayload)). RequestPayload indicates the request body.

    • Hash() indicates the hash algorithm. Only the SHA256 algorithm is supported. For example, if the encryption method of the signature string is ACS3-HMAC-SHA256, you must use SHA256 as the hash algorithm.

    • HexEncode() encodes the hash value in Base16. This function returns an encoded hash value in the hexadecimal format in lowercase letters.

    Important

    If the request body is empty, such as in a GET request, use an empty string as the value of the RequestPayload parameter. All request parameters of an API operation are defined in the query string. Therefore, you can use an empty string as the value of the RequestPayload parameter.

    Table 1: Mappings among encryption methods of the signature string, signature calculation algorithms, and hash algorithms

    Encryption method of the signature string (SignatureAlgorithm)

    Hash algorithm used to process RequestPayload and CanonicalRequest (Hash)

    Algorithm for signature calculation

    (SignatureMethod)

    ACS3-HMAC-SHA256

    SHA256

    HMAC-SHA256

Step 2: Construct a string-to-sign

Construct a string-to-sign based on the following pseudocode:

StringToSign =
    SignatureAlgorithm + '\n' +
    HashedCanonicalRequest
  • SignatureAlgorithm

    The encryption method of the signature string. Only ACS3-HMAC-SHA256 is supported. The MD5- or SHA1-based algorithms are no longer supported.

  • HashedCanonicalRequest

    The hash value of the canonicalized request. The following pseudocode shows how to generate the hash value:

    HashedCanonicalRequest = HexEncode(Hash(CanonicalRequest))
  1. Calculate the hash value of the canonicalized request that is obtained in Step 1. Select a hash algorithm based on the encryption method of the signature string, which is specified by the SignatureAlgorithm parameter. For more information, see the "Table 1" section of this topic. Only ACS3-HMAC-SHA256 can be used as the encryption method. In this case, you must use SHA256 as the hash algorithm.

  2. Encode the hash value that is obtained in the previous step in Base16.

Step 3: Calculate the signature string

Calculate the signature string based on the following pseudocode:

Signature = HexEncode(SignatureMethod(Secret, StringToSign))
  • StringToSign: the string-to-sign that is constructed in Step 2. The value is encoded in UTF-8.

  • SignatureMethod: the algorithm for signature calculation. Select an algorithm based on the encryption method of the signature string, which is specified by the SignatureAlgorithm parameter. For more information, see the "Table 1" section of this topic.

  • Secret: the AccessKey secret provided by Alibaba Cloud. The value is in the binary format.

  • HexEncode: the function that is used to encode values in Base16.

Step 4: Add the signature string to the request

After you obtain the signature string, specify the Authorization header in the request in the following format: Authorization:<SignatureAlgorithm> Credential=<AccessKeyId>,SignedHeaders=<SignedHeaders>,Signature=<Signature>. Example:

Authorization:ACS3-HMAC-SHA256 Credential=YourAccessKeyId,SignedHeaders=content-type;host;x-acs-timestamp,Signature=6b595d672d79c15b18edb4ccfba6789a24a6f2b82c400e03162d9279b08555d7

Signature examples

Example with fixed parameters

In this example, the RunInstances operation of Elastic Compute Service (ECS) is called. Your AccessKey ID is YourAccessKeyId.

Your AccessKey secret is YourAccessKeySecret. The value of the x-acs-signature-nonce header is 3156853299f313e23d1673dc12e1703d, and the timestamp of the request is 2023-10-26T10:22:32Z. You can perform the following steps to sign the request:

  1. Construct a canonicalized request.

POST
/
ImageId=win2019_1809_x64_dtc_zh-cn_40G_alibase_20230811.vhd&RegionId=cn-shanghai
host:ecs.cn-shanghai.aliyuncs.com
x-acs-action:RunInstances
x-acs-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-acs-date:2023-10-26T10:22:32Z
x-acs-signature-nonce:3156853299f313e23d1673dc12e1703d
x-acs-version:2014-05-26

host;x-acs-action;x-acs-content-sha256;x-acs-date;x-acs-signature-nonce;x-acs-version
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  1. Construct a string-to-sign.

ACS3-HMAC-SHA256
7ea06492da5221eba5297e897ce16e55f964061054b7695beedaac1145b1e259
  1. Calculate the signature string.

06563a9e1b43f5dfe96b81484da74bceab24a1d853912eee15083a6f0f3283c0
  1. Add the signature string to the request.

POST /?ImageId=win2019_1809_x64_dtc_zh-cn_40G_alibase_20230811.vhd&RegionId=cn-shanghai HTTP/1.1
Authorization: ACS3-HMAC-SHA256 Credential=YourAccessKeyId,SignedHeaders=host;x-acs-action;x-acs-content-sha256;x-acs-date;x-acs-signature-nonce;x-acs-version,Signature=06563a9e1b43f5dfe96b81484da74bceab24a1d853912eee15083a6f0f3283c0
x-acs-action: RunInstances
host: ecs.cn-shanghai.aliyuncs.com
x-acs-date: 2023-10-26T09:01:01Z
x-acs-version: 2014-05-26
x-acs-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-acs-signature-nonce: d410180a5abf7fe235dd9b74aca91fc0
user-agent: AlibabaCloud (Mac OS X; x86_64) Java/1.8.0_352-b08 tea-util/0.2.6 TeaDSL/1
accept: application/json
Note

To help you understand the preceding signature method, this topic provides the following sample code to completely implement the signature method in mainstream programming languages. The following sample code is provided only to help you understand the signature method and is not globally applicable. We recommend that you use SDKs for the actual development.

Java

To use the signature method in Java, you must install Maven dependencies.

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.SimpleTimeZone;

public class SignatureDemo {
    /**
     * The AccessKey ID and AccessKey secret provided by Alibaba Cloud. 
     * In this example, the AccessKey ID and AccessKey Secret are obtained by using the environment variables. 
     */
    private final static String ACCESS_KEY_ID = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
    private final static String ACCESS_KEY_SECRET = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");

    /**
     * The tool that is used to format dates. The tool can format a DATETIME string into a value in the yyyy-MM-dd'T'HH:mm:ss'Z format. 
     * This format is commonly used by Alibaba Cloud APIs to process DATETIME data. 
     */
    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

    /**
     * Use the HMAC-SHA256 algorithm to generate a Message Authentication Code (MAC) signature. 
     *
     * @param key The key that is used to generate the MAC signature, which must be kept confidential. 
     * @param msg The content to be used for MAC signature calculation. 
     * @return The MAC signature that is calculated by using the HMAC-SHA256 algorithm. 
     * @throws Exception The error that is reported when the MAC signature generator is initialized or the MAC signature is calculated. 
     */
    public static byte[] hmac256(byte[] key, String msg) throws Exception {
        // Obtain an object on which the HMAC-SHA256 algorithm is implemented.
        Mac mac = Mac.getInstance("HmacSHA256");
        // Create a key standard to initialize the MAC signature generator.
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
        // Initialize the MAC signature generator.
        mac.init(secretKeySpec);
        // Calculate the MAC signature and return the signature.
        return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * Calculate the hash value of the signature string by using the SHA-256 algorithm and return the hash value as a string in the hexadecimal format. 
     *
     * @param str The string to be calculated by using the SHA-256 algorithm. 
     * @return The string in the hexadecimal format in lowercase letters. 
     * @throws Exception The error that is reported when you obtain the object on which the HMAC-SHA256 algorithm is implemented. 
     */
    public static String sha256Hex(String str) throws Exception {
        // Obtain the object on which the SHA-256 algorithm is implemented.
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        // Calculate the hash value of the string by using the SHA-256 algorithm.
        byte[] d = md.digest(str.getBytes(StandardCharsets.UTF_8));
        // Convert the hash value to a string in the hexadecimal format in lowercase letters and return the string.
        return DatatypeConverter.printHexBinary(d).toLowerCase();
    }

    /**
     * The main function is used to show how to send an API request by using Alibaba Cloud SDK for Java. 
     * Construct a request based on the specified parameters and perform signature authentication. 
     *
     * @param args args
     * @throws Exception The errors that may be reported. The errors include but are not limited to network errors and invalid date formats. 
     */
    public static void main(String[] args) throws Exception {
        // Initialize the basic request parameters.
        String host = "ecs.cn-beijing.aliyuncs.com";  // endpoint
        String regionId = "cn-beijing";  // The region ID.
        String action = "DescribeInstances";  // The operation that you want to perform.
        String version = "2014-05-26"; // The API version number.
        String algorithm = "ACS3-HMAC-SHA256";  // The encryption method of the signature string.
        SDF.setTimeZone(new SimpleTimeZone(0, "GMT")); // Set the time zone for date formatting to GMT.
        String xAcsDate=SDF.format (new Date()); // Generate a GMT string of the current time.
        System.out.println("xAcsDate=========>" + xAcsDate);
        String signatureNonce=java.util.UUID.randomUUID().toString(); // Generate a unique and random number that is used to prevent replay attacks.
        System.out.println("signatureNonce=========>" + signatureNonce);

        // Step 1: Construct a canonicalized request.
        String httpRequestMethod = "GET";
        // The request path. If the resource path is empty, use a forward slash (/) as the value of the CanonicalURI parameter.
        String canonicalUri = "/";
        // The request parameters. If the query string is empty, use an empty string as the canonicalized query string, which is a blank line.
        String canonicalQueryString = "RegionId=" + regionId;
        // The request body. If the request body is empty, such as in a GET request, use an empty string as the value of the RequestPayload parameter.
        String requestPayload = "";
        // Calculate the hash value of the request body.
        String hashedRequestPayload = sha256Hex(requestPayload);
        // Construct request headers. Concatenate multiple canonicalized headers by the lowercase header name in alphabetical order.
        String canonicalHeaders = "host:" + host.trim() + "\n"
                + "x-acs-action:" + action.trim() + "\n"
                + "x-acs-content-sha256:" + hashedRequestPayload.trim() + "\n"
                + "x-acs-date:" + xAcsDate.trim() + "\n"
                + "x-acs-signature-nonce:" + signatureNonce.trim() + "\n"
                + "x-acs-version:" + version.trim() + "\n";
        // The request headers that are used for signature calculation. Use semicolons (;) to concatenate all the headers by lowercase header name in alphabetical order.
        String signedHeaders = "host;x-acs-action;x-acs-content-sha256;x-acs-date;x-acs-signature-nonce;x-acs-version";
        String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n"
                + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;
        System.out.println("canonicalRequest=========>" + canonicalRequest);

        // Step 2: Construct a string-to-sign.
        String hashedCanonicalRequest = sha256Hex(canonicalRequest); // Calculate the hash value of the canonicalized request.
        String stringToSign = algorithm + "\n" + hashedCanonicalRequest;
        System.out.println("stringToSign=========>" + stringToSign);

        // Step 3: Calculate the signature string.
        String signature = DatatypeConverter.printHexBinary(hmac256(ACCESS_KEY_SECRET.getBytes(StandardCharsets.UTF_8), stringToSign)).toLowerCase();
        System.out.println("signature=========>" + signature);

        // Step 4: Specify the Authorization header.
        String authorization = algorithm + " " + "Credential=" + ACCESS_KEY_ID + ",SignedHeaders=" + signedHeaders + ",Signature=" + signature;
        System.out.println("authorization=========>" + authorization);


        // Send the request by using HttpClient.
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String url = "https://ecs.cn-beijing.aliyuncs.com";
        URIBuilder uriBuilder = new URIBuilder(url);
        // Configure request parameters.
        uriBuilder.addParameter("RegionId", regionId);
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        // Add request headers.
        httpGet.addHeader("Authorization", authorization);
        httpGet.addHeader("host", host);
        httpGet.addHeader("x-acs-action", action);
        httpGet.addHeader("x-acs-content-sha256", hashedRequestPayload);
        httpGet.addHeader("x-acs-date", xAcsDate);
        httpGet.addHeader("x-acs-version", version);
        httpGet.addHeader("x-acs-signature-nonce", signatureNonce);
        // Send the request.
        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            System.out.println(result);
        } catch (IOException e) {
            // Handle errors.
            e.printStackTrace();
        }
    }
}

Python

You need to manually install the pytz and requests libraries. Run the following commands on the terminal based on your Python version:

Python 3

pip3 install pytz
pip3 install requests

Python 2

pip install pytz
pip install requests
import binascii
import hashlib
import hmac
import os
import uuid
from datetime import datetime
from urllib.parse import urlencode

import pytz
import requests


def hmac256(key: bytes, msg: str) -> bytes:
    # Use the HMAC-SHA256 algorithm to calculate the signature string.
    mac = hmac.new(key, msg.encode('utf-8'), hashlib.sha256)
    return mac.digest()


def sha256_hex(str: str) -> str:
    # Calculate the hash value of the signature string by using the SHA-256 algorithm.
    hash_value = hashlib.sha256(str.encode('utf-8')).digest()
    # Convert the hash value to a string in the hexadecimal format in lowercase letters and return the string.
    return binascii.hexlify(hash_value).decode().lower()


if __name__ == '__main__':
    access_key_id = os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID']
    access_key_secret = os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
    host = 'ecs.cn-beijing.aliyuncs.com'
    region_id = 'cn-beijing'
    action = 'DescribeInstances'
    version = '2014-05-26'
    algorithm = 'ACS3-HMAC-SHA256'
    now = datetime.now()
    # Convert the current time to a time string in GMT.
    gmt = now.astimezone(pytz.utc)
    # Format the time to a value in the ISO 8601 standard. Z indicates UTC/GMT.
    x_acs_date = gmt.strftime("%Y-%m-%dT%H:%M:%SZ")
    signature_nonce = str(uuid.uuid4())

    # Step 1: Construct a canonicalized request.
    http_request_method = "GET"
    canonical_uri = "/"
    canonical_query_string = "RegionId=" + region_id
    request_payload = ""
    hashed_request_payload = sha256_hex(request_payload)
    canonical_headers = (
            "host:" + host.strip() + "\n"
            + "x-acs-action:" + action.strip() + "\n"
            + "x-acs-content-sha256:" + hashed_request_payload.strip() + "\n"
            + "x-acs-date:" + x_acs_date.strip() + "\n"
            + "x-acs-signature-nonce:" + signature_nonce.strip() + "\n"
            + "x-acs-version:" + version.strip() + "\n"
    )
    signed_headers = "host;x-acs-action;x-acs-content-sha256;x-acs-date;x-acs-signature-nonce;x-acs-version"
    canonical_request = (http_request_method + "\n" +
                         canonical_uri + "\n" +
                         canonical_query_string + "\n" +
                         canonical_headers + "\n" +
                         signed_headers + "\n" +
                         hashed_request_payload)
    print(canonical_request)
    # Step 2: Construct a string-to-sign.
    hashed_canonical_request = sha256_hex(canonical_request)
    string_to_sign = algorithm + "\n" + hashed_canonical_request
    print(string_to_sign)

    # Step 3: Calculate the signature string.
    signature = hmac256(access_key_secret.encode('utf-8'), string_to_sign).hex().lower()
    print(signature)

    # Step 4: Specify the Authorization header.
    authorization = f"{algorithm} Credential={access_key_id},SignedHeaders={signed_headers},Signature={signature}"
    print(authorization)

    # Send a request by using the requests library.
    url = "https://ecs.cn-beijing.aliyuncs.com"
    # Generate the request URL.
    params = {"RegionId": region_id}
    encoded_params = urlencode(params)
    full_url = f"{url}?{encoded_params}"
    # Construct the request headers.
    headers = {
        "Authorization": authorization,
        "host": host,
        "x-acs-action": action,
        "x-acs-content-sha256": hashed_request_payload,
        "x-acs-date": x_acs_date,
        "x-acs-version": version,
        "x-acs-signature-nonce": signature_nonce,
    }
    # Send a GET request and process the response.
    try:
        response = requests.get(full_url, headers=headers)
        response.raise_for_status()  # An error is reported if the returned status code is not 2xx.
        result = response.text
        print(result)
    except requests.exceptions.RequestException as e:
        # Handle errors.
        print(f"An error occurred: {e}")

Go

You need to manually run the following commands:

go get github.com/google/uuid
package main

import (
    "bytes"
    "context"
    "crypto/hmac"
    "crypto/sha256"
    "crypto/tls"
    "encoding/hex"
    "fmt"
    "github.com/google/uuid"
    "io"
    "net/http"
    "os"
    "strings"
    "time"
)

func hmac256(key []byte, toSignString string) ([]byte, error) {
    // Obtain the object on which the HMAC-SHA256 algorithm is implemented.
    h := hmac.New(sha256.New, key)

    // Construct a string-to-sign.
    _, err := h.Write([]byte(toSignString))
    if err != nil {
       return nil, err
    }

    // Calculate the hash value of the signature string and return the hash value.
    return h.Sum(nil), nil
}

func sha256Hex(str string) string {
    // Obtain the object on which the SHA-256 algorithm is implemented.
    hash := sha256.New()

    // Write the signature string to the hash function.
    _, _ = hash.Write([]byte(str))

    // Calculate the hash value of the signature string by using the SHA-256 algorithm and return the hash value as a string in the hexadecimal format in lowercase letters.
    hexString := hex.EncodeToString(hash.Sum(nil))

    return hexString
}

func main() {
    accessKeyId := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")
    accessKeySecret := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
    host := "ecs.cn-beijing.aliyuncs.com" // endpoint
    regionId := "cn-beijing"              // The region ID.
    action := "DescribeInstances"         // The operation that you want to perform.
    version := "2014-05-26"               // The API version number.
    algorithm := "ACS3-HMAC-SHA256"       // The encryption method of the signature string.
    // Create a Location object that is fixed in the UTC time zone, which is equivalent to GMT in Java.
    gmt := time.FixedZone("GMT", 0)
    // Obtain the current time and specify the time in the UTC time zone.
    now := time.Now().In(gmt)
    // Format the current time.
    xAcsDate := now.Format("2006-01-02T15:04:05Z")
    signatureNonce := uuid.New().String()

    // Step 1: Construct a canonicalized request.
    httpRequestMethod := "GET"
    canonicalUri := "/"
    canonicalQueryString := "RegionId=" + regionId
    requestPayload := ""
    hashedRequestPayload := sha256Hex(requestPayload)
    canonicalHeaders := "host:" + strings.Trim(host, " ") + "\n" +
       "x-acs-action:" + strings.Trim(action, " ") + "\n" +
       "x-acs-content-sha256:" + strings.Trim(hashedRequestPayload, " ") + "\n" +
       "x-acs-date:" + strings.Trim(xAcsDate, " ") + "\n" +
       "x-acs-signature-nonce:" + strings.Trim(signatureNonce, " ") + "\n" +
       "x-acs-version:" + strings.Trim(version, " ") + "\n"
    signedHeaders := "host;x-acs-action;x-acs-content-sha256;x-acs-date;x-acs-signature-nonce;x-acs-version"
    canonicalRequest := httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload

    // Step 2: Construct a string-to-sign.
    hashedCanonicalRequest := sha256Hex(canonicalRequest)
    stringToSign := algorithm + "\n" + hashedCanonicalRequest

    // Step 3: Calculate the signature string.
    byteData, err := hmac256([]byte(accessKeySecret), stringToSign)
    if err != nil {
       fmt.Println(err)
    }
    signature := strings.ToLower(hex.EncodeToString(byteData))

    // Step 4: Specify the Authorization header.
    authorization := algorithm + " " + "Credential=" + accessKeyId + ",SignedHeaders=" + signedHeaders + ",Signature=" + signature

    // Generate the request URL.
    url := fmt.Sprintf("https://%s/?RegionId=%s", host, regionId)

    // Create an HTTP client.
    tr := &http.Transport{
       TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // If you want to skip SSL verification, retain this line. Otherwise, delete the line or set the InsecureSkipVerify parameter to false.
    }
    client := &http.Client{Transport: tr}

    // Construct a request
    req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, nil)
    if err != nil {
       panic(err)
    }

    // Add request headers.
    req.Header.Set("Authorization", authorization)
    req.Header.Set("Host", host)
    req.Header.Set("x-acs-action", action)
    req.Header.Set("x-acs-content-sha256", hashedRequestPayload)
    req.Header.Set("x-acs-date", xAcsDate)
    req.Header.Set("x-acs-version", version)
    req.Header.Set("x-acs-signature-nonce", signatureNonce)

    // Send the request and process the response.
    resp, err := client.Do(req)
    if err != nil {
       panic(err)
    }
    defer func(Body io.ReadCloser) {
       err := Body.Close()
       if err != nil {

       }
    }(resp.Body)
    var respBuffer bytes.Buffer
    _, err = io.Copy(&respBuffer, resp.Body)
    if err != nil {
       panic(err)
    }
    respBytes := respBuffer.Bytes()
    fmt.Println(string(respBytes))
}