You must sign all HTTP and HTTPS API requests to ensure security. Alibaba Cloud verifies the identity of a request sender based on the request signature. Alibaba Cloud uses an AccessKey pair to perform symmetric encryption and verify the identity of the request sender.

Note
  • An AccessKey pair serves as a logon credential that is used to call API operations, and the username and password are used to log on to the Apsara File Storage NAS console. The AccessKey ID is used to verify the identity of the user, and the AccessKey secret is used to encrypt and verify the signature string. You must keep your AccessKey secret confidential. For more information, see Obtain an AccessKey pair.
  • NAS provides SDKs in multiple programming languages and supports third-party SDKs. The SDKs allow you to sign requests in a more efficient manner. For more information, see SDK overview.

Step 1: Construct a canonicalized query string

  1. Sort the request parameters in alphabetical order. Sort the request parameters in alphabetical order. The request parameters include common request parameters and operation-specific parameters except Signature.
    Note If you use the GET method to submit a request, the parameters that follow the question mark (?) and are connected by ampersands (&) in the request uniform resource identifier (URI) are request parameters.
  2. Encode the canonicalized query string in UTF-8. Follow RFC 3986 to encode parameters and their values based on the following rules:
    • Uppercase letters, lowercase letters, digits, hyphens (-), underscores (_), and periods (.) do not need to be encoded.
    • Other characters must be percent-encoded in the %XY format. XY represents the ASCII code of the characters in hexadecimal notation. For example, double quotation marks (") are encoded into %22.
    • Extended UTF-8 characters are encoded in the %XY%ZA… format.
    • Space characters must be encoded into %20. Do not encode space characters into plus signs (+).

    The RFC 3986-based encoding method is different from the application/x-www-form-urlencoded MIME encoding algorithm, such as the java.net.URLEncoder class in the Java standard library. If you use the RFC 3986-based encoding method, you can encode a string based on a standard library. Then, you can replace each plus sing (+) in the encoded string with %20 and replace each asterisk (*) in the encoded string with %2A. After you complete these steps, an encoded string that comply with the preceding rules is generated. To implement the algorithm, you can use the following percentEncode method:

    private static final String ENCODING = "UTF-8";
    
    private static String percentEncode(String value) throws UnsupportedEncodingException {
     return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A") : null;
    }       
  3. Use equal signs (=) to connect the encoded parameter names and values.
  4. Use an ampersand (&) to connect the encoded request parameters. These parameters must be sorted in the same order as those in Step 1.

After you complete the preceding steps, a canonicalized query string (CanonicalizedQueryString) that follows the request syntax is generated. For more information, see Request syntax.

Step 2: Create a string-to-sign

  1. Create a string-to-sign (StringToSign). You can also use percentEncode to encode the canonicalized query string that is generated in the Step 1. Take note of the following rules when you create a string-to-sign:
    StringToSign=
      HTTPMethod + "&" + //HTTPMethod: The HTTP method that is used to send the request, such as GET. 
      percentEncode("/") + "&" + //percentEncode("/"): Encodes backslashes (/) into %2F. 
      percentEncode(CanonicalizedQueryString) // Encodes the canonicalized query string that is generated in Step 1. 
  2. Calculate the hash-based message authentication code (HMAC) value of the string-to-sign based on RFC 2104. Use the Secure Hash Algorithm 1 (SHA-1) algorithm to calculate the HMAC value. In this example, the Java Base64 encoding method is used.
    Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
    Note When you calculate the signature, your AccessKey secret followed by an ampersand (&) is used as the key value required by RFC 2104. The ASCII value of the key value is 38. For more information, see Obtain an AccessKey pair.
  3. Encode the Signature parameter based on RFC 3986 and add the parameter to the canonicalized query string.

Example 1: Concatenate parameters

In this example, the DescribeRegions operation is called. The following example shows the signature process when AccessKeyID is set to testid and AccessKeySecret is set to testsecret.

  1. Create a canonicalized query string.
    http://nas.cn-hangzhou.aliyuncs.com/?Timestamp=2021-11-30T09%3A18%3A51Z&Format=JSON&AccessKeyId=testid&Action=DescribeRegions&SignatureMethod=HMAC-SHA1&SignatureNonce=47b920a4f8fb2769d2404b74860e3e5d&Version=2017-06-26&SignatureVersion=1.0
  2. Create a string-to-sign (StringToSign).
    GET&%2F&AccessKeyId%3Dtestid%26Action%3DDescribeRegions%26Format%3DXML%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf%26SignatureVersion%3D1.0%26Timestamp%3D2021-11-11T12%253A46%253A24Z%26Version%3D2017-06-26
  3. Calculate the signature value. If AccessKeySecret is set to testsecret, testsecret& is used as the key value to calculate the signature. The calculated signature is OLeaidS1JvxuMvnyHOwuJ+uX5qY=. In this example, the Java Base64 encoding method is used.
    Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
  4. Add the Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D string that is encoded based on RFC 3986 to the URL in Step 1.
    http://nas.cn-hangzhou.aliyuncs.com/?SignatureVersion=1.0&Action=DescribeRegions&Format=JSON&SignatureNonce=47b920a4f8fb2769d2404b74860e3e5d&Version=2017-06-26&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2021-11-30T12%253A46%253A24Z

The new URL allows you to send an HTTP request from a browser or a tool such as cURL and Wget to call the DescribeRegions operation, which is used to query Alibaba Cloud regions.

Example 2: Use the standard library of the programming language

In this example, the DescribeRegions operation is called. The following example shows the signature process when AccessKeyID is set to testid, AccessKeySecret is set to testsecret, and all request parameters are placed in a Java Map<String, String> object:

  1. Predefine the encoding method.
    private static final String ENCODING = "UTF-8";
    private static String percentEncode(String value) throws UnsupportedEncodingException {
      return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A") : null;
    }
  2. Predefine the time format for the Timestamp parameter. The value of the Timestamp parameter must be specified in the ISO 8601 standard. The time must be in UTC.
    private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
    private static String formatIso8601Date(Date date) {
      SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
      df.setTimeZone(new SimpleTimeZone(0, "GMT"));
      return df.format(date);
    }
  3. Create a query string.
    final String HTTP_METHOD = "GET";
    Map<String, String> parameters = new HashMap<>();
    // Configures request parameters.
    parameters.put("Action", "DescribeRegions");
    parameters.put("Version", "2017-06-26");
    parameters.put("AccessKeyId", "testid");
    parameters.put("Timestamp", formatIso8601Date(new Date()));
    parameters.put("SignatureMethod", "HMAC-SHA1");
    parameters.put("SignatureVersion", "1.0");
    parameters.put("SignatureNonce", UUID.randomUUID().toString());
    parameters.put("Format", "JSON");
    // Sorts the request parameters.
    String[] sortedKeys = parameters.keySet().toArray(new String[]{});
    Arrays.sort(sortedKeys);
    final String SEPARATOR = "&";
    // Creates a string-to-sign.
    StringBuilder stringToSign = new StringBuilder();
    stringToSign.append(HTTP_METHOD).append(SEPARATOR);
    stringToSign.append(percentEncode("/")).append(SEPARATOR);
    StringBuilder canonicalizedQueryString = new StringBuilder();
    for(String key : sortedKeys) {
    // Encodes the key and value.
      canonicalizedQueryString.append("&")
      .append(percentEncode(key)).append("=")
      .append(percentEncode(parameters.get(key)));
    }
    // Encodes the canonicalized query string.
    stringToSign.append(percentEncode(
      canonicalizedQueryString.toString().substring(1)));
  4. Calculate the signature. If AccessKeySecret is set to testsecret, testsecret& is used as the key value to calculate the signature. The calculated signature is OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D.
    // Calculates the signature.
    final String ALGORITHM = "HmacSHA1";
    final String ENCODING = "UTF-8";
    key = "testsecret&";
    Mac mac = Mac.getInstance(ALGORITHM);
    mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM));
    byte[] signData = mac.doFinal(stringToSign.toString().getBytes());
    String signature = Base64 .getEncoder().encodeToString(signData);
    // Prints the canonicalized query string.
    String url = parameters.entrySet().stream()
        .map(e -> String.format("%s=%s", e.getKey(), percentEncode(e.getValue())))
        .collect(Collectors.joining("&", "http://nas.cn-hangzhou.aliyuncs.com/?", "&Signature=" + percentEncode(signature)));
    System.out.println("url: " + url);

    Encode the Signature parameter based on RFC 3986 and add the result to the canonicalized query string. The following URL is obtained:

    http://nas.cn-hangzhou.aliyuncs.com/?AccessKeyId=testid&Action=DescribeRegions&Format=JSON&SignatureMethod=HMAC-SHA1&SignatureNonce=a7568db9-3647-4a3b-9f49-6cd9cd51c28a&SignatureVersion=1.0&Timestamp=2021-11-30T09%3A46%3A11Z&Version=2017-06-26&Signature=7LgzXFA0qiWbH0L2fFk0qbYyGC8%3D
  5. Use a browser or a tool such as cURL or Wget to send an HTTP request.
    {
        "TotalCount":25,
        "RequestId":"A66FCCB9-4538-193F-A67A-2E0A515A****",
        "PageSize":10,
        "PageNumber":1,
        "Regions":{
            "Region":[
                {
                    "RegionId":"cn-hangzhou",
                    "RegionEndpoint":"nas.cn-hangzhou.aliyuncs.com",
                    "LocalName":"China (Hangzhou)"
                },
                {
                    "RegionId":"cn-shanghai",
                    "RegionEndpoint":"nas.cn-shanghai.aliyuncs.com",
                    "LocalName":"China (Shanghai)"
                }
            ]
        }
    }

The response contains regions and region IDs. If you set Format to XML when you submit a request, the response is returned in the XML format instead of the JSON format. For more information, see Responses.