To obtain a token using OpenAPI, you must write code for identity verification and request logic. You can use this method if an SDK is not available for your programming language or if you want to control dependent components. This topic describes how to obtain a token using OpenAPI.
Request message
A client sends a request to the server to obtain a token. The server then returns a response that contains the result of the token creation. The client can send requests over HTTP or HTTPS using the GET or POST method. The server provides an API based on the Alibaba Cloud Portable OpenAPI Proxy (POP) protocol. Therefore, the client must implement the Alibaba Cloud POP signature mechanism.
Because the request parameter settings are the same for HTTP and HTTPS, this topic uses an HTTP request as an example.
URL
Protocol
URL
Method
HTTP/1.1
http://nls-meta.cn-shanghai.aliyuncs.com/
GET/POST
Request parameters
Name
Type
Required
Description
AccessKeyId
String
Yes
The AccessKey ID of your Alibaba Cloud account.
Action
String
Yes
The name of the POP API operation: CreateToken
Version
String
Yes
The version of the POP API: 2019-02-28
Format
String
Yes
The format of the response: JSON
RegionId
String
Yes
The ID of the region where the service is deployed: cn-shanghai
Timestamp
String
Yes
The timestamp of the request. The time must be in UTC and follow the ISO 8601 standard. Use the YYYY-MM-DDThh:mm:ssZ format. For example, 2019-04-03T06:15:03Z is 06:15:03 on April 3, 2019 (UTC).
SignatureMethod
String
Yes
The signature algorithm: HMAC-SHA1
SignatureVersion
String
Yes
The version of the signature algorithm: 1.0
SignatureNonce
String
Yes
A unique random number (UUID) to prevent replay attacks. Each request must have a unique UUID. The format is A-B-C-D-E, where the character counts are 8-4-4-4-12. For example, 8d1e6a7a-f44e-40d5-aedb-fe4a1c80f434.
Signature
String
Yes
The signature string that is calculated based on all request parameters. For information about how to generate the signature, see the "Signature mechanism" section.
NoteIf you use the GET method, add the request parameters to the request line:
/?request_parameter_string.If you use the POST method, add the request parameters to the request body.
HTTP request header
The HTTP request header consists of key-value pairs. Each pair is on a separate line, and the key and value are separated by a colon (:). The following table describes the header fields.
Name
Type
Required
Description
Host
String
No
The domain name of the server that receives the HTTP request:
nls-meta.cn-shanghai.aliyuncs.com. This is typically parsed automatically from the request URL.Accept
String
No
The content type that the client can accept:
application/json. If you do not set this parameter, the default value */* is used.Content-type
String
Required for the POST method
The data format of the request body for a POST request:
application/x-www-form-urlencoded.
Sample messages:
HTTP GET request message
GET /?Signature=O0s6pfeOxtFM6YKSZKQdSyPR9Vs%3D&AccessKeyId=LTAF3sAA****&Action=CreateToken&Format=JSON&RegionId=cn-shanghai&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: nls-meta.cn-shanghai.aliyuncs.com User-Agent: curl/7.49.1 Accept: */*HTTP POST request message
POST / HTTP/1.1 Host: nls-meta.cn-shanghai.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=cn-shanghai&Timestamp=2019-03-25T09%3A07%3A52Z
Response result:
After you send an HTTP request to obtain a token, the server returns a response. The result is a JSON string in the response body. The response is the same for both GET and POST methods.
Successful response
The HTTP status code is 200. The following table describes the response fields.
Parameter
Type
Description
Token
Token object
Contains the token value and its expiration timestamp.
Id
String
The token value assigned to the request.
ExpireTime
Long
The expiration timestamp of the token, in seconds. For example, the UNIX timestamp 1553825814 corresponds to 10:16:54 on March 29, 2019 (UTC+8). The token is valid before this time.
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 content of the response body, which is a JSON string.
{ "NlsRequestId": "dd05a301b40441c99a2671905325****", "RequestId": "E11F2DC2-0163-4D97-A704-0BD28045****", "ErrMsg": "", "Token": { "ExpireTime": 1553592564, "Id": "889******166", "UserId": "150**********151" } }Error response
An HTTP status code other than 200 is returned. The following table describes the response fields.
Parameter
Type
Description
RequestId
String
The request ID.
Message
String
The error message returned for the failed response.
Code
String
The error code returned for the failed response.
NoteUse the error code and error message to check if the request parameters are set correctly.
The following response message is an example of an error caused by an incorrect 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":"nls-meta.cn-shanghai.aliyuncs.com","Code":"InvalidAccessKeyId.NotFound"}The response body contains the following JSON string.
{ "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": "nls-meta.cn-shanghai.aliyuncs.com", "Code": "InvalidAccessKeyId.NotFound" }
Signature mechanism
The server authenticates the sender of each POP API request. Therefore, you must include signature information in each HTTP or HTTPS request. The signature mechanism allows the server to identify the user who sends a request and verify that the request has not been tampered with during transmission.
Security verification process:
To calculate a signature, you need the AccessKey ID and AccessKey secret from your Alibaba Cloud account. The HMAC-SHA1 algorithm is used for symmetric encryption. The workflow is as follows.
The client generates a signature string based on the API request content. The content includes the HTTP request parameters and the request body.
The client uses the AccessKey ID and AccessKey secret of the Alibaba Cloud account to sign the signature string from the previous step. This process produces the digital signature for the API request.
The client sends the API request content and the digital signature to the server.
After the server receives the request, it repeats steps 1 and 2 to calculate the expected digital signature. The server retrieves the user key for the request from the backend.
The server compares the expected digital signature with the one sent by the client. If they match, the request passes verification. Otherwise, the server rejects the request.
Generate a signature string for the request:
Construct a canonicalized query string.
Construct a canonicalized query string from the HTTP request parameters, excluding the Signature parameter, by following these steps:
Sort the request parameters by parameter name in case-sensitive alphabetical order.
URL-encode the sorted request parameters.
URL-encode the request parameter names and values using the
UTF-8character set according to the following rules:Characters A-Z, a-z, 0-9, and the special characters
-,_,., and~do not need to be encoded.Other characters are percent-encoded into the "%XY" format, where XY is the hexadecimal representation of the character's ASCII code. For example, a double quotation mark (") is encoded as %22.
Extended
UTF-8characters are encoded into the "%XY%ZA..." format.A space must be encoded as %20, not a plus sign (
+).
NoteMost libraries that support URL encoding, such as java.net.URLEncoder in Java, encode according to the rules of the "application/x-www-form-urlencoded" Multipurpose Internet Mail Extensions (MIME) type. You can use this encoding method directly. Then, you must replace the plus sign (
+) with%20, the asterisk (*) with%2A, and%7Ewith a tilde (~) in the encoded string to obtain a string that follows the rules described above.Use an equal sign (
=) to connect the URL-encoded parameter name and value:percentEncode(ParameterKey) + "=" + percentEncode(ParameterValue).Use an ampersand (
&) to connect the URL-encoded request parameter pairs, such asAction=CreateToken&Format=JSON.NoteDo not add an ampersand (
&) before the first parameter name in the string.Returns the canonicalized query string.
For example:
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 parameters. for (String key : sortedKeys) { canonicalizedQueryString.append("&") .append(percentEncode(key)).append("=") .append(percentEncode(queryParamsMap.get(key))); } queryString = canonicalizedQueryString.toString().substring(1);NoteFor the complete code, see the
canonicalizedQueryfunction in the "Complete examples" section.Constructed canonicalized query string:
AccessKeyId=LTA******3s2&Action=CreateToken&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=f20b1beb-e5dc-4245-9e96-aa582e905c1a&SignatureVersion=1.0&Timestamp=2019-04-03T03%3A40%3A13Z&Version=2019-02-28Construct the string-to-sign.
Create the string-to-sign by connecting the HTTP request method (GET), the URL-encoded URI of the request (/), and the canonicalized query string from step 1 with ampersands (
&). The format isHTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(queryString).The following code shows an example of how to construct the 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 the complete code, see the
createStringToSignfunction in the "Complete examples" section.Constructed string-to-sign:
GET&%2F&AccessKeyId%3DLTA******F3s%26Action%3DCreateToken%26Format%3DJSON%26RegionID%3Dcn-shanghai%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3Da237e025-07ea-4d87-bb04-d9b2712d871d%26SignatureVersion%3D1.0%26Timestamp%3D2019-04-19T03%253A31%253A40Z%26Version%3D2019-02-28Calculate the signature.
The signature is calculated using the HMAC-SHA1 algorithm with Base64, and the encoding is
UTF-8.Use the HMAC-SHA1 algorithm to calculate the digital signature of the string-to-sign from step 2. Use your AccessKey secret as the key. You must append an ampersand (
&) to the AccessKey secret that is used for the calculation.The signature must also be URL-encoded.
The following code shows an example of how to calculate the signature:
signature = Base64( HMAC-SHA1(stringToSign, accessKeySecret + "&") ); // URL-encode the signature signature = percentEncode(signature)NoteFor the complete code, see the
signfunction in the "Complete examples" section.Calculated signature:
# Signature string AKIktdPUMCV12fTh667BLXeuCtg= # URL-encoded result AKIktdPUMCV12fTh667BLXeuCtg%3DAfter you calculate the signature, connect the signature key-value pair with an equal sign (
=) and add it to the request string from step 1 using an ampersand (&). You can then use this string as the HTTP GET request parameter to send to the server to obtain a token.String queryStringWithSign = "Signature=" + signature + "&" + queryString;
Quick test
You can use the following parameters to calculate a signature and compare the result with the expected output.
The provided AccessKey ID and AccessKey secret are not real, and the timestamp has expired. A signature calculated with these parameters will fail if you try to obtain a token. These parameters are for signature calculation testing and comparison only.
AccessKey ID
my_access_key_idAccessKey secret:
my_access_key_secretTimestamp:
2019-04-18T08:32:31ZSignatureNonce:
b924c8c3-6d03-4c5d-ad36-d984d3116788
The request parameters are as follows:
AccessKeyId:my_access_key_id
Action:CreateToken
Version:2019-02-28
Timestamp:2019-04-18T08:32:31Z
Format:JSON
RegionId:cn-shanghai
SignatureMethod:HMAC-SHA1
SignatureVersion:1.0
SignatureNonce:b924c8c3-6d03-4c5d-ad36-d984d3116788Canonicalize the request string.
AccessKeyId=my_access_key_id&Action=CreateToken&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=b924c8c3-6d03-4c5d-ad36-d984d3116788&SignatureVersion=1.0&Timestamp=2019-04-18T08%3A32%3A31Z&Version=2019-02-28Construct the string-to-sign.
GET&%2F&AccessKeyId%3Dmy_access_key_id%26Action%3DCreateToken%26Format%3DJSON%26RegionId%3Dcn-shanghai%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3Db924c8c3-6d03-4c5d-ad36-d984d3116788%26SignatureVersion%3D1.0%26Timestamp%3D2019-04-18T08%253A32%253A31Z%26Version%3D2019-02-28Calculate the signature.
hHq4yNsPitlfDJ2L0nQPdugdEzM= # URL-encoded result hHq4yNsPitlfDJ2L0nQPdugdEzM%3DObtain the request string with the signature.
Signature=hHq4yNsPitlfDJ2L0nQPdugdEzM%3D&AccessKeyId=my_access_key_id&Action=CreateToken&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=b924c8c3-6d03-4c5d-ad36-d984d3116788&SignatureVersion=1.0&Timestamp=2019-04-18T08%3A32%3A31Z&Version=2019-02-28Assemble the HTTP request URL.
http://nls-meta.cn-shanghai.aliyuncs.com/?Signature=hHq4yNsPitlfDJ2L0nQPdugdEzM%3D&AccessKeyId=my_access_key_id&Action=CreateToken&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=b924c8c3-6d03-4c5d-ad36-d984d3116788&SignatureVersion=1.0&Timestamp=2019-04-18T08%3A32%3A31Z&Version=2019-02-28You can obtain the token using the HTTP request link from step 5 with a browser or curl.
curl "http://nls-meta.cn-shanghai.aliyuncs.com/?Signature=${YourSignature}&AccessKeyId=${YourAccessKeyId}&Action=CreateToken&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=${YourRequestUUID}&SignatureVersion=1.0&Timestamp=${YourRequestTimestamp}&Version=2019-02-28"
Complete examples
This topic provides sample code in Java and Python. You can implement client programs in other languages based on the protocol and these examples.
Before you call the API, you must configure environment variables to read your access credentials. The environment variables for the Intelligent Speech Interaction AccessKey ID and AccessKey secret are ALIYUN_AK_ID and ALIYUN_AK_SECRET, respectively.
Java example
Dependency file:
<!-- 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; /** * Get the timestamp. * The timestamp must be in UTC and comply with the ISO 8601 standard. The time zone is +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); } /** * Get the UUID. */ public static String getUniqueNonce() { UUID uuid = UUID.randomUUID(); return uuid.toString(); } /** * URL-encode the string. * Use the UTF-8 character set to encode request parameters and their values according to 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 parameters, canonicalize them, and combine them into a request 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 request parameter string: " + queryString); } catch (UnsupportedEncodingException e) { System.out.println("UTF-8 encoding is not supported."); e.printStackTrace(); } return queryString; } /*** * Construct the string-to-sign. * @param method The HTTP request method. * @param urlPath The URI of the request. * @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("Constructed 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 Alibaba Cloud AccessKey secret, 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 the token and its expiration timestamp. * @param queryString Request parameters. */ public static void processGETRequest(String queryString) { /** * Set up the HTTP GET request. * 1. Use the HTTP protocol. * 2. Token service domain name: nls-meta.cn-shanghai.aliyuncs.com * 3. Request path: / * 4. Set the request parameters. */ String url = "http://nls-meta.cn-shanghai.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 submit the request to obtain a token: " + result); } } else { System.err.println("Failed to submit the request to obtain a 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 = System.getenv().get("ALIYUN_AK_ID"); String accessKeySecret = System.getenv().get("ALIYUN_AK_SECRET"); 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", "cn-shanghai"); queryParamsMap.put("SignatureMethod", "HMAC-SHA1"); queryParamsMap.put("SignatureVersion", "1.0"); queryParamsMap.put("SignatureNonce", getUniqueNonce()); /** * 1. Construct the canonicalized query string. */ String queryString = canonicalizedQuery(queryParamsMap); if (null == queryString) { System.out.println("Failed to construct the canonicalized query string!"); return; } /** * 2. Construct the string-to-sign. */ String method = "GET"; // The HTTP method for sending the request, GET. String urlPath = "/"; // Request path. String stringToSign = createStringToSign(method, urlPath, queryString); if (null == stringToSign) { System.out.println("Failed to construct 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 request string from Step 1. */ String queryStringWithSign = "Signature=" + signature + "&" + queryString; System.out.println("Request string with signature: " + queryStringWithSign); /** * 5. Send an HTTP GET request to obtain the token. */ processGETRequest(queryStringWithSign); if (token != null) { System.out.println("Obtained token: " + token + ", expiration timestamp (seconds): " + expireTime); // Convert the 10-digit timestamp to UTC+8. String expireDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(expireTime * 1000)); System.out.println("Token expiration time (UTC+8): " + expireDate); } } }Python example
NotePython 3.4 or later is required.
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': 'cn-shanghai', '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'} # Construct the canonicalized query string. query_string = AccessToken._encode_dict(parameters) print('Canonicalized query string: %s' % query_string) # Construct the 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) # URL-encode the signature. signature = AccessToken._encode_text(signature) print('URL-encoded signature: %s' % signature) # Call the service. full_url = 'http://nls-meta.cn-shanghai.aliyuncs.com/?Signature=%s&%s' % (signature, query_string) print('url: %s' % full_url) # Submit 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__": # User information. access_key_id = os.getenv('ALIYUN_AK_ID') # Read AccessKey ID from environment variables. access_key_secret = os.getenv('ALIYUN_AK_SECRET') # Read AccessKey secret from environment variables. 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('Token expiration time (UTC+8): %s' % (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(expire_time))))
References
You can also obtain a token in the following ways: