This topic describes how to obtain an access token by calling an API operation.
Request
The client sends a request to the server to obtain an access token. The server creates an access token and then returns a response to the client. The client can use the GET or POST method to send HTTP or HTTPS requests. The server provides the Portable OpenAPI Proxy (POP) API. Therefore, the client must use the Alibaba Cloud POP signature mechanism to add a signature to each request.
Request parameter settings are the same for HTTP and HTTPS. This topic uses HTTP as an example to describe how to send a request to obtain an access token.
URL
Protocol
URL
Method
HTTP/1.1
http://nlsmeta.ap-southeast-1.aliyuncs.com/
GET/POST
Request parameters
Parameter
Type
Required
Description
AccessKeyId
String
Yes
The AccessKey ID of the Alibaba Cloud account.
Action
String
Yes
The API operation that you want to perform. Set this parameter to CreateToken.
Version
String
Yes
The version number of the POP API. Set this parameter to 2019-02-28.
Format
String
Yes
The format of the response. Set this parameter to JSON.
RegionId
String
Yes
The region ID of the service. Set this parameter to ap-southeast-1.
Timestamp
String
Yes
The timestamp of the request. Specify the time in the ISO 8601 standard in the yyyy-MM-ddTHH:mm:ssZ format. The time must be in UTC+0. For example, a value of 2019-04-03T06:15:03Z specifies 06:15:03 on April 3, 2019.
SignatureMethod
String
Yes
The signature algorithm. Set this parameter to HMAC-SHA1.
SignatureVersion
String
Yes
The version number of the signature algorithm. Set this parameter to 1.0.
SignatureNonce
String
Yes
A unique random number that is used to prevent replay attacks. You must use different numbers for different requests. The value is in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12) format. Example: 8d1e6a7a-f44e-40d5-aedb-fe4a1c80f434.
Signature
String
Yes
The signature string that is calculated based on all request parameters. For more information about the signature calculation method, see the Signature mechanism section.
NoteIf you use the GET method, you must add the request parameters to the request line in the following format:
/?request parameter string
.If you use the POST method, you must add the request parameters to the request body.
HTTP request header
The HTTP request header consists of key-value pairs. Each key-value pair is a field that occupies a line. The key and the value in each pair are separated with a colon (:). The following table describes the fields of the HTTP request header.
Parameter
Type
Required
Description
Host
String
No
The endpoint of the requested Intelligent Speech Interaction service. Set this field to
nlsmeta.ap-southeast-1.aliyuncs.com
. This endpoint is usually automatically resolved based on the request URL.Accept
String
No
The type of content that the client can receive. Set this field to
application/json
. If you do not specify this field, the default value */* is used.Content-type
String
Yes for the POST method
The data format of the request body if the POST method is used. Set this field to
application/x-www-form-urlencoded
.
Sample requests:
HTTP GET request
GET /?Signature=O0s6pfeOxtFM6YKSZKQdSyPR9Vs%3D&AccessKeyId=LTAF3sAA****&Action=CreateToken&Format=JSON&RegionId=ap-southeast-1&SignatureMethod=HMAC-SHA1&SignatureNonce=a1f01895-6ff1-43c1-ba15-6c109fa00106&SignatureVersion=1.0&Timestamp=2019-03-27T09%3A51%3A25Z&Version=2019-02-28 HTTP/1.1 Host: nlsmeta.ap-southeast-1.aliyuncs.com User-Agent: curl/7.49.1 Accept: */*
HTTP POST request
POST / HTTP/1.1 Host: nlsmeta.ap-southeast-1.aliyuncs.com User-Agent: curl/7.49.1 Accept: */* Content-type: application/x-www-form-urlencoded Content-Length: 276 SignatureVersion=1.0&Action=CreateToken&Format=JSON&SignatureNonce=8d1e6a7a-f44e-40d5-aedb-fe4a1c80f434&Version=2019-02-28&AccessKeyId=LTAF3sAA****&Signature=oT8A8RgvFE1tMD%2B3hDbGuoMQSi8%3D&SignatureMethod=HMAC-SHA1&RegionId=ap-southeast-1&Timestamp=2019-03-25T09%3A07%3A52Z
Responses:
After the client sends an HTTP request to obtain an access token, the server returns a response. The result is stored as a JSON string in the response. The response is the same for the GET and POST methods.
Success response
The HTTP status code is 200. The following table describes the response parameters.
Parameter
Type
Description
Token
Object
The token object that contains the access token and the timestamp that indicates the validity period of the access token.
Id
String
The access token that is assigned to the request.
ExpireTime
Long
The timestamp that indicates the validity period of the access token. Unit: seconds. For example, a value of 1553825814 indicates that the access token is valid before 10:16:54 (UTC+8) on March 29, 2019.
HTTP/1.1 200 OK Date: Mon, 25 Mar 2019 09:29:24 GMT Content-Type: application/json; charset=UTF-8 Content-Length: 216 Connection: keep-alive Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-Requested-With, X-Sequence, _aop_secret, _aop_signature Access-Control-Max-Age: 172800 Server: Jetty(7.2.2.v20101205) {"NlsRequestId":"dd05a301b40441c99a2671905325****","RequestId":"E11F2DC2-0163-4D97-A704-0BD28045****","ErrMsg":"","Token":{"ExpireTime":1553592564,"Id":"88916699****","UserId":"150151111111****"}}
The following code shows the response body in the JSON format:
{ "NlsRequestId": "dd05a301b40441c99a2671905325****", "RequestId": "E11F2DC2-0163-4D97-A704-0BD28045****", "ErrMsg": "", "Token": { "ExpireTime": 1553592564, "Id": "889******166", "UserId": "150**********151" } }
Error response
The HTTP status code is not 200. The following table describes the response parameters.
Parameter
Type
Description
RequestId
String
The ID of the request.
Message
String
The error message of the error response.
Code
String
The error code of the error response.
NoteCheck whether the request parameters are properly set based on the error code and the error message.
The following example shows an error response that is caused by an invalid AccessKey ID:
HTTP/1.1 404 Not Found Date: Thu, 28 Mar 2019 07:23:01 GMT Content-Type: application/json; charset=UTF-8 Content-Length: 290 Connection: keep-alive Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-Requested-With, X-Sequence, _aop_secret, _aop_signature Access-Control-Max-Age: 172800 Server: Jetty(7.2.2.v20101205) {"Recommend":"https://error-center.aliyun.com/status/search?Keyword=InvalidAccessKeyId.NotFound&source=PopGw","Message":"Specified access key is not found.","RequestId":"A51587CB-5193-4DB8-9AED-CD4365C2****","HostId":"nlsmeta.ap-southeast-1.aliyuncs.com","Code":"InvalidAccessKeyId.NotFound"}
The following code shows the response body in the JSON format:
{ "Recommend": "https://error-center.aliyun.com/status/search?Keyword=InvalidAccessKeyId.NotFound&source=PopGw", "Message": "Specified access key is not found.", "RequestId": "A51587CB-5193-4DB8-9AED-CD4365C2****", "HostId": "nlsmeta.ap-southeast-1.aliyuncs.com", "Code": "InvalidAccessKeyId.NotFound" }
Signature method
When the server receives a POP API request, it authenticates the identity of the API caller. Therefore, the HTTP or HTTPS request must contain signature information. Based on the signature mechanism, the server can identify the user that sends the API request and confirm whether the API request is tampered with during network transmission.
Security verification process
Intelligent Speech Interaction uses the HMAC-SHA1 algorithm to implement symmetric encryption based on the AccessKey ID and the AccessKey secret of your Alibaba Cloud account. The following process shows how to verify an API request:
The client generates a string signature based on the content of an API request that includes the HTTP request parameters and the request body.
The client uses the AccessKey ID and the AccessKey secret of your Alibaba Cloud account to encrypt the signature string that is generated in Step 1. Then, the client obtains a digital signature for this API request.
The client sends the signed API request to the server.
After the server receives the API request, it repeats Steps 1 and 2 to calculate the expected digital signature for the API request. The server can obtain the AccessKey ID and the AccessKey secret that are used by the API request from the backend.
The server compares the expected digital signature with the digital signature that is sent from the client. If the signatures are the same, the request passes the security verification. If the signatures are different, the server rejects the API request.
Generate a signature string for an API request
Create a canonicalized query string.
Create a canonicalized query string based on the HTTP request parameters but do not include the Signature parameter. To create a canonicalized query string, perform the following steps:
Sort the request parameters in alphabetical order. Parameter names are case-sensitive.
Encode the parameters. Canonicalize the sorted request parameters.
Encode the names and values of the request parameters in
UTF-8
based on the following rules:Uppercase letters, lowercase letters, digits, and some special characters such as hyphens (
-
), underscores (_
), periods (.
), and tildes (~
) 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 as %22.
Extended
UTF-8
characters must be encoded in the %XY%ZA… format.Spaces must be encoded as %20. Do not encode spaces as plus signs (
+
).
NoteMost libraries that support URL encoding, such as java.net.URLEncoder, are created based on the encoding rules of application/x-www-form-urlencoded. application/x-www-form-urlencoded is a subtype of Multipurpose Internet Mail Extensions (MIME). If you use this encoding method, you can replace a plus sign (
+
) with%20
, an asterisk (*
) with%2A
, and%7E
with a tilde (~
) in the encoded string to obtain the required string.Use an equal sign (
=
) to connect the name and the value of each URL encoded request parameter. Example:percentEncode (parameter key) + "=" + percentEncode (parameter value)
.Use an ampersand (
&
) to connect the key-value pairs of the URL encoded request parameters that are generated in Step c. Example:Action=CreateToken&Format=JSON
.NoteDo not add an ampersand (
&
) before the first parameter name of the canonicalized query string.Return the canonicalized query string.
Sample code:
String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, URL_ENCODING) .replace("+", "%20") .replace("*", "%2A") .replace("%7E", "~") : null; } // Sort the parameter keys. String[] sortedKeys = queryParamsMap.keySet().toArray(new String[] {}); Arrays.sort(sortedKeys); // Encode and concatenate the sorted request parameters. for (String key : sortedKeys) { canonicalizedQueryString.append("&") .append(percentEncode(key)).append("=") .append(percentEncode(queryParamsMap.get(key))); } queryString = canonicalizedQueryString.toString().substring(1);
NoteFor more information about the complete sample code, see the
canonicalizedQuery
function in the Complete sample code section.The following canonicalized query string is created:
AccessKeyId=LTA******3s2&Action=CreateToken&Format=JSON&RegionId=ap-southeast-1&SignatureMethod=HMAC-SHA1&SignatureNonce=f20b1beb-e5dc-4245-9e96-aa582e905c1a&SignatureVersion=1.0&Timestamp=2019-04-03T03%3A40%3A13Z&Version=2019-02-28
Create a string-to-sign.
A string-to-sign consists of the HTTP request method, the URL encoded URL, and the URL encoded canonicalized query string that is obtained in Step 1. Use ampersands (
&
) to concatenate these elements in the following format:HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(queryString)
.The following sample code provides an example to show how to create a string-to-sign:
StringBuilder strBuilderSign = new StringBuilder(); strBuilderSign.append(HTTPMethod); strBuilderSign.append("&"); strBuilderSign.append(percentEncode(urlPath)); strBuilderSign.append("&"); strBuilderSign.append(percentEncode(queryString)); stringToSign = strBuilderSign.toString();
NoteFor more information about the complete sample code, see the
createStringToSign
function in the Complete sample code section.The following string-to-sign is created:
Calculate the signature.
Use the HMAC-SHA1 algorithm and Base64 to calculate the HMAC value of the string-to-sign. Then, encode the calculated HMAC value in
UTF-8
.Use the SHA1 algorithm to calculate the HMAC value of the string-to-sign that is created in Step 2. The AccessKey secret is used as the key for the HMAC calculation. You must add an ampersand (
&
) after the AccessKey secret.Perform URL encoding for the calculated signature.
The following sample code provides an example to show how to calculate the signature:
signature = Base64( HMAC-SHA1(stringToSign, accessKeySecret + "&") ); // Perform URL encoding signature = percentEncode(signature)
NoteFor more information about the complete sample code, see the
sign
function in the Complete sample code section.The following signature is calculated:
# The HMAC value of the string-to-sign AKIktdPUMCV12fTh667BLXeuCtg= # The URL encoded signature AKIktdPUMCV12fTh667BLXeuCtg%3D
After the signature is calculated, use an equal sign (
=
) to connect the key and the value of the Signature parameter. Then, use an ampersand (&
) to connect the Signature parameter and the canonicalized query string that is obtained in Step 1. Then, the client can send the signed HTTP GET request to the server to obtain an access token.String queryStringWithSign = "Signature=" + signature + "&" + queryString;
Quick test
Use the following parameters to calculate a signature and test the calculated signature.
The AccessKey ID and the AccessKey secret are not real. The timestamp has expired. You cannot obtain an access token by using the signature that is calculated based on these parameters. These parameters are used only to calculate and test a signature.
AccessKeyId:
my_access_key_id
AccessKeySecret:
my_access_key_secret
Timestamp:
2019-04-18T08:32:31Z
SignatureNonce:
b924c8c3-6d03-4c5d-ad36-d984d3116788
The following request parameters are used:
AccessKeyId:my_access_key_id
Action:CreateToken
Version:2019-02-28
Timestamp:2019-04-18T08:32:31Z
Format:JSON
RegionId:ap-southeast-1
SignatureMethod:HMAC-SHA1
SignatureVersion:1.0
SignatureNonce:b924c8c3-6d03-4c5d-ad36-d984d3116788
Create a canonicalized query string.
AccessKeyId=my_access_key_id&Action=CreateToken&Format=JSON&RegionId=ap-southeast-1&SignatureMethod=HMAC-SHA1&SignatureNonce=b924c8c3-6d03-4c5d-ad36-d984d3116788&SignatureVersion=1.0&Timestamp=2019-04-18T08%3A32%3A31Z&Version=2019-02-28
Create a string-to-sign.
Calculate and obtain the signature.
hHq4yNsPitlfDJ2L0nQPdugdEzM= # The URL encoded signature hHq4yNsPitlfDJ2L0nQPdugdEzM%3D
Add the signature to the canonicalized query string.
Signature=hHq4yNsPitlfDJ2L0nQPdugdEzM%3D&AccessKeyId=my_access_key_id&Action=CreateToken&Format=JSON&RegionId=ap-southeast-1&SignatureMethod=HMAC-SHA1&SignatureNonce=b924c8c3-6d03-4c5d-ad36-d984d3116788&SignatureVersion=1.0&Timestamp=2019-04-18T08%3A32%3A31Z&Version=2019-02-28
Obtain the HTTP request URL.
http://nlsmeta.ap-southeast-1.aliyuncs.com/?Signature=hHq4yNsPitlfDJ2L0nQPdugdEzM%3D&AccessKeyId=my_access_key_id&Action=CreateToken&Format=JSON&RegionId=ap-southeast-1&SignatureMethod=HMAC-SHA1&SignatureNonce=b924c8c3-6d03-4c5d-ad36-d984d3116788&SignatureVersion=1.0&Timestamp=2019-04-18T08%3A32%3A31Z&Version=2019-02-28
Enter the HTTP request URL that is obtained in Step 5 in the address bar of your browser or run the following curl command to obtain an access token.
curl "http://nlsmeta.ap-southeast-1.aliyuncs.com/?Signature=${Your signature}&AccessKeyId=${Your AccessKey ID}&Action=CreateToken&Format=JSON&RegionId=ap-southeast-1&SignatureMethod=HMAC-SHA1&SignatureNonce=${Your request UUID}&SignatureVersion=1.0&Timestamp=${Your request timestamp}&Version=2019-02-28"
Complete sample code
This section provides the sample code for Java and Python. You can write the code for client programs in other languages based on these protocols and sample code.
Demo for Java
Add the following dependency:
<!-- http://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.9.1</version> </dependency>
Sample code:
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.SimpleTimeZone; import java.util.UUID; public class CreateToken { private final static String TIME_ZONE = "GMT"; private final static String FORMAT_ISO8601 = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private final static String URL_ENCODING = "UTF-8"; private static final String ALGORITHM_NAME = "HmacSHA1"; private static final String ENCODING = "UTF-8"; private static String token = null; private static long expireTime = 0; /** * Obtain the timestamp. * Specify the time in the ISO 8601 standard in the yyyy-MM-ddTHH:mm:ssZ format. The time must be in UTC+0. */ public static String getISO8601Time(Date date) { Date nowDate = date; if (null == date) { nowDate = new Date(); } SimpleDateFormat df = new SimpleDateFormat(FORMAT_ISO8601); df.setTimeZone(new SimpleTimeZone(0, TIME_ZONE)); return df.format(nowDate); } /** * Obtain the UUID of the request. */ public static String getUniqueNonce() { UUID uuid = UUID.randomUUID(); return uuid.toString(); } /** * Perform URL encoding. * Use UTF-8 to encode the names and values of the request parameters based on RFC 3986. */ public static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, URL_ENCODING).replace("+", "%20") .replace("*", "%2A").replace("%7E", "~") : null; } /*** * Sort the request parameters and concatenate the sorted request parameters to create a canonicalized query string. * @param queryParamsMap All request parameters. * @return The canonicalized query string. */ public static String canonicalizedQuery( Map<String, String> queryParamsMap) { String[] sortedKeys = queryParamsMap.keySet().toArray(new String[] {}); Arrays.sort(sortedKeys); String queryString = null; try { StringBuilder canonicalizedQueryString = new StringBuilder(); for (String key : sortedKeys) { canonicalizedQueryString.append("&") .append(percentEncode(key)).append("=") .append(percentEncode(queryParamsMap.get(key))); } queryString = canonicalizedQueryString.toString().substring(1); System.out.println("Canonicalized query string: " + queryString); } catch (UnsupportedEncodingException e) { System.out.println("UTF-8 encoding is not supported."); e.printStackTrace(); } return queryString; } /*** * Create a string-to-sign. * @param method The HTTP request method. * @param urlPath The HTTP request URL. * @param queryString The canonicalized query string. * @return The string-to-sign. */ public static String createStringToSign(String method, String urlPath, String queryString) { String stringToSign = null; try { StringBuilder strBuilderSign = new StringBuilder(); strBuilderSign.append(method); strBuilderSign.append("&"); strBuilderSign.append(percentEncode(urlPath)); strBuilderSign.append("&"); strBuilderSign.append(percentEncode(queryString)); stringToSign = strBuilderSign.toString(); System.out.println("string-to-sign: " + stringToSign); } catch (UnsupportedEncodingException e) { System.out.println("UTF-8 encoding is not supported."); e.printStackTrace(); } return stringToSign; } /*** * Calculate the signature. * @param stringToSign The string-to-sign. * @param accessKeySecret The AccessKey secret that is appended with an ampersand (&). * @return The calculated signature. */ public static String sign(String stringToSign, String accessKeySecret) { try { Mac mac = Mac.getInstance(ALGORITHM_NAME); mac.init(new SecretKeySpec( accessKeySecret.getBytes(ENCODING), ALGORITHM_NAME )); byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING)); String signBase64 = DatatypeConverter.printBase64Binary(signData); System.out.println("Calculated signature: " + signBase64); String signUrlEncode = percentEncode(signBase64); System.out.println("URL encoded signature: " + signUrlEncode); return signUrlEncode; } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e.toString()); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException(e.toString()); } catch (InvalidKeyException e) { throw new IllegalArgumentException(e.toString()); } } /*** * Send an HTTP GET request to obtain an access token and the timestamp that indicates the validity period of the access token. * @param queryString The request parameters. */ public static void processGETRequest(String queryString) { /** * Create an HTTP GET request. * 1. Use HTTP. * 2. Use the endpoint of Intelligent Speech Interaction: nlsmeta.ap-southeast-1.aliyuncs.com * 3. Request URL: / * 4. Set the request parameters. */ String url = "http://nlsmeta.ap-southeast-1.aliyuncs.com"; url = url + "/"; url = url + "?" + queryString; System.out.println("HTTP request URL: " + url); Request request = new Request.Builder() .url(url) .header("Accept", "application/json") .get() .build(); try { OkHttpClient client = new OkHttpClient(); Response response = client.newCall(request).execute(); String result = response.body().string(); if (response.isSuccessful()) { JSONObject rootObj = JSON.parseObject(result); JSONObject tokenObj = rootObj.getJSONObject("Token"); if (tokenObj != null) { token = tokenObj.getString("Id"); expireTime = tokenObj.getLongValue("ExpireTime"); } else{ System.err.println("Failed to send the request to obtain an access token: " + result); } } else { System.err.println("Failed to send the request to obtain an access token: " + result); } response.close(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String args[]) { if (args.length < 2) { System.err.println("CreateTokenDemo need params: <AccessKey Id> <AccessKey Secret>"); System.exit(-1); } String accessKeyId = args[0]; String accessKeySecret = args[1]; System.out.println(getISO8601Time(null)); // All request parameters. Map<String, String> queryParamsMap = new HashMap<String, String>(); queryParamsMap.put("AccessKeyId", accessKeyId); queryParamsMap.put("Action", "CreateToken"); queryParamsMap.put("Version", "2019-02-28"); queryParamsMap.put("Timestamp", getISO8601Time(null)); queryParamsMap.put("Format", "JSON"); queryParamsMap.put("RegionId", "ap-southeast-1"); queryParamsMap.put("SignatureMethod", "HMAC-SHA1"); queryParamsMap.put("SignatureVersion", "1.0"); queryParamsMap.put("SignatureNonce", getUniqueNonce()); /** * 1. Create a canonicalized query string. */ String queryString = canonicalizedQuery(queryParamsMap); if (null == queryString) { System.out.println("Failed to create the canonicalized query string."); return; } /** * 2. Create a string-to-sign. */ String method = "GET"; // The HTTP request method, such as GET. String urlPath = "/"; // The HTTP request URL. String stringToSign = createStringToSign(method, urlPath, queryString); if (null == stringToSign) { System.out.println("Failed to create the string-to-sign."); return; } /** * 3. Calculate the signature. */ String signature = sign(stringToSign, accessKeySecret + "&"); if (null == signature) { System.out.println("Failed to calculate the signature.") return; } /** * 4. Add the signature to the canonicalized query string that is obtained in Step 1. */ String queryStringWithSign = "Signature=" + signature + "&" + queryString; System.out.println("Query string that contains the signature: " + queryStringWithSign); /** * 5. Send the HTTP GET request to obtain an access token. */ processGETRequest(queryStringWithSign); if (token != null) { System.out.println("Obtained token: " + token + ", Timestamp of the validity period (unit: seconds): "+ expireTime); // Convert the 10-digit timestamp to a time in UTC+8. String expireDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(expireTime * 1000)); System.out.println("Validity period of the access token in UTC+8: " + expireDate); } } }
Demo for Python
NoteThe Python version must be Python 3.4 or later.
Run the following command to install the Python HTTP library Requests:
pip install requests
#!/usr/bin/env python # -*- coding: utf-8 -*- import base64 import hashlib import hmac import requests import time import uuid from urllib import parse class AccessToken: @staticmethod def _encode_text(text): encoded_text = parse.quote_plus(text) return encoded_text.replace('+', '%20').replace('*', '%2A').replace('%7E', '~') @staticmethod def _encode_dict(dic): keys = dic.keys() dic_sorted = [(key, dic[key]) for key in sorted(keys)] encoded_text = parse.urlencode(dic_sorted) return encoded_text.replace('+', '%20').replace('*', '%2A').replace('%7E', '~') @staticmethod def create_token(access_key_id, access_key_secret): parameters = {'AccessKeyId': access_key_id, 'Action': 'CreateToken', 'Format': 'JSON', 'RegionId': 'ap-southeast-1', 'SignatureMethod': 'HMAC-SHA1', 'SignatureNonce': str(uuid.uuid1()), 'SignatureVersion': '1.0', 'Timestamp': time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), 'Version': '2019-02-28'} # Create a canonicalized query string. query_string = AccessToken._encode_dict(parameters) print('Canonicalized query string: %s' % query_string) # Create a string-to-sign. string_to_sign = 'GET' + '&' + AccessToken._encode_text('/') + '&' + AccessToken._encode_text(query_string) print('string-to-sign: %s' % string_to_sign) # Calculate the signature. secreted_string = hmac.new(bytes(access_key_secret + '&', encoding='utf-8'), bytes(string_to_sign, encoding='utf-8'), hashlib.sha1).digest() signature = base64.b64encode(secreted_string) print('Signature: %s' % signature) // Encode the calculated signature. signature = AccessToken._encode_text(signature) print('URL encoded signature: %s' % signature) # Create an HTTP GET request. full_url = 'http://nlsmeta.ap-southeast-1.aliyuncs.com/?Signature=%s&%s' % (signature, query_string) print('url: %s' % full_url) # Send the HTTP GET request. response = requests.get(full_url) if response.ok: root_obj = response.json() key = 'Token' if key in root_obj: token = root_obj[key]['Id'] expire_time = root_obj[key]['ExpireTime'] return token, expire_time print(response.text) return None, None if __name__ == "__main__": # The user information. access_key_id = 'Your AccessKey ID' access_key_secret = 'Your AccessKey secret' token, expire_time = AccessToken.create_token(access_key_id, access_key_secret) print('token: %s, expire time(s): %s' % (token, expire_time)) if expire_time: print('Validity period of the token in UTC+8: %s' % (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(expire_time))))