日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

通過OpenAPI獲取Token

更新時(shí)間:

通過OpenAPI獲取Token的方式,要求開發(fā)者自行編寫代碼完成身份驗(yàn)證和請求邏輯,如果對應(yīng)的編程語言缺少SDK,或者需要控制依賴組件,可以通過OpenAPI獲取Token。本文介紹如何通過OpenAPI獲取Token。

請求報(bào)文

客戶端向服務(wù)端發(fā)送獲取Token的請求,服務(wù)端返回創(chuàng)建Token結(jié)果的響應(yīng)。客戶端發(fā)送的請求支持使用HTTP/HTTPS協(xié)議,請求方法支持GET/POST方法。服務(wù)端提供了基于阿里云POP協(xié)議的接口,因此客戶端需要實(shí)現(xiàn)阿里云POP的簽名機(jī)制。

由于HTTPS協(xié)議的請求參數(shù)設(shè)置與HTTP協(xié)議相同,下面以HTTP協(xié)議請求為例,介紹如何發(fā)送請求獲取Token。

  • URL

    協(xié)議

    URL

    方法

    HTTP/1.1

    http://nls-meta.cn-shanghai.aliyuncs.com/

    GET/POST

  • 請求參數(shù)

    名稱

    類型

    是否必選

    說明

    AccessKeyId

    String

    阿里云賬號(hào)AccessKey ID

    Action

    String

    POP API名稱:CreateToken

    Version

    String

    POP API版本:2019-02-28

    Format

    String

    響應(yīng)返回的類型:JSON

    RegionId

    String

    服務(wù)所在的地域ID:cn-shanghai

    Timestamp

    String

    請求的時(shí)間戳。日期格式按照ISO 8601標(biāo)準(zhǔn)表示,且使用UTC時(shí)間,時(shí)區(qū):+0。格式:YYYY-MM-DDThh:mm:ssZ。如2019-04-03T06:15:03Z為UTC時(shí)間2019年4月3日6點(diǎn)15分03秒

    SignatureMethod

    String

    簽名算法:HMAC-SHA1

    SignatureVersion

    String

    簽名算法版本:1.0

    SignatureNonce

    String

    唯一隨機(jī)數(shù)uuid,用于請求的防重放攻擊,每次請求唯一,不能重復(fù)使用。格式為A-B-C-D-E(A、B、C、D、E的字符位數(shù)分別為8、4、4、4、12)。例如,8d1e6a7a-f44e-40d5-aedb-fe4a1c80f434。

    Signature

    String

    由所有請求參數(shù)計(jì)算出的簽名結(jié)果,生成方法參見下文簽名機(jī)制。

    說明

    • 使用GET方法,需要將請求參數(shù)設(shè)置在請求行中:/?請求參數(shù)字符串

    • 使用POST方法,需要將請求參數(shù)設(shè)置在請求體中。

  • HTTP請求頭部

    HTTP請求頭部由“關(guān)鍵字-值”對組成,每行一對,關(guān)鍵字和值用英文冒號(hào)“:”分隔,內(nèi)容如下:

    名稱

    類型

    是否必選

    描述

    Host

    String

    HTTP請求的服務(wù)器域名:nls-meta.cn-shanghai.aliyuncs.com,一般根據(jù)請求鏈接自動(dòng)解析。

    Accept

    String

    指定客戶端能夠接收的內(nèi)容類型:application/json,不設(shè)置默認(rèn)為 */* 。

    Content-type

    String

    POST方法必須設(shè)置

    指定POST方法請求體數(shù)據(jù)格式:application/x-www-form-urlencoded

報(bào)文示例:

  • HTTP GET請求報(bào)文

    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請求報(bào)文

    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

響應(yīng)結(jié)果:

發(fā)送獲取Token的HTTP請求后,會(huì)受到服務(wù)端響應(yīng),結(jié)果以JSON字符串的形式保存在響應(yīng)中,GET方法和POST方法的響應(yīng)結(jié)果相同。

  • 成功響應(yīng)

    HTTP狀態(tài)碼為200,響應(yīng)字段如下表所示。

    參數(shù)

    類型

    說明

    Token

    Token對象

    包含Token值和有效期時(shí)間戳。

    Id

    String

    請求分配的Token值。

    ExpireTime

    Long

    Token的有效期時(shí)間戳(單位:秒。例如1553825814換算為北京時(shí)間為:2019/3/29 10:16:54,即Token在該時(shí)間之前有效。)。

    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****"}}

    響應(yīng)體JSON字符串內(nèi)容如下。

    {
        "NlsRequestId": "dd05a301b40441c99a2671905325****",
        "RequestId": "E11F2DC2-0163-4D97-A704-0BD28045****",
        "ErrMsg": "",
        "Token": {
            "ExpireTime": 1553592564,
            "Id": "889******166",
            "UserId": "150**********151"
        }
    }
  • 失敗響應(yīng)

    HTTP狀態(tài)碼為非200,響應(yīng)字段說明如下表。

    參數(shù)

    類型

    說明

    RequestId

    String

    請求ID

    Message

    String

    失敗響應(yīng)的錯(cuò)誤信息

    Code

    String

    失敗響應(yīng)的錯(cuò)誤碼

    說明

    請根據(jù)錯(cuò)誤碼和錯(cuò)誤信息提示檢查請求參數(shù)是否設(shè)置正確。

    以重傳入阿里云賬號(hào)的AccessKey Id錯(cuò)誤為例,響應(yīng)消息如下。

    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"}

    響應(yīng)體JSON字符串內(nèi)容如下。

    {
        "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"
    }

簽名機(jī)制

服務(wù)端POP API對每個(gè)接口訪問請求的發(fā)送者都要進(jìn)行身份驗(yàn)證,所以無論使用HTTP協(xié)議還是HTTPS協(xié)議提交的請求,都需要在請求中包含簽名信息。通過簽名機(jī)制,服務(wù)端可以確認(rèn)哪位用戶在做API請求,并能確認(rèn)請求在網(wǎng)絡(luò)傳輸過程中是否被篡改。

安全驗(yàn)證流程

計(jì)算簽名時(shí),需要阿里云賬號(hào)的AccessKey Id和AccessKey Secret,使用HMAC-SHA1算法進(jìn)行對稱加密。其工作流程如下。

  1. 請求端根據(jù)API請求內(nèi)容(包括HTTP請求參數(shù)和請求體)生成簽名字符串。

  2. 請求端使用阿里云賬號(hào)的AccessKey Id和AccessKey Secret對第一步生成的簽名字符串進(jìn)行簽名,獲得該API請求的數(shù)字簽名。

  3. 請求端把API請求內(nèi)容和數(shù)字簽名一同發(fā)送給服務(wù)端。

  4. 服務(wù)端在接收到請求后會(huì)重復(fù)12步驟(服務(wù)端會(huì)在后臺(tái)獲取該請求使用的用戶密鑰)并計(jì)算出該請求期望的數(shù)字簽名。

  5. 服務(wù)端用期望的數(shù)字簽名和請求端發(fā)送過來的數(shù)字簽名做對比,若完全一致則認(rèn)為該請求通過驗(yàn)證。否則拒絕該請求。

生成請求的簽名字符串

  1. 構(gòu)造規(guī)范化的請求字符串。

    將HTTP請求參數(shù)(不包括Signature)構(gòu)造成規(guī)范化的請求字符串。規(guī)范化步驟:

    1. 參數(shù)排序。按參數(shù)名的字典順序,對請求參數(shù)進(jìn)行大小寫敏感排序。

    2. 參數(shù)編碼。對排序后的請求參數(shù)進(jìn)行規(guī)范化設(shè)置。

      請求參數(shù)名和值都要使用UTF-8字符集進(jìn)行URL編碼,URL編碼規(guī)則如下:

      • 對于字符 A-Z、a-z、0-9以及字符-_.~不編碼。

      • 對于其他字符編碼成“%XY”的格式,其中XY是字符對應(yīng)ASCII碼的16進(jìn)制表示。比如英文的雙引號(hào)(”)對應(yīng)的編碼就是%22。

      • 對于擴(kuò)展的UTF-8字符,編碼成“%XY%ZA…”的格式。

      • 需要說明的是英文空格要被編碼為%20,而不是加號(hào)+

      說明

      一般支持URL編碼的庫(比如Java中的java.net.URLEncoder)都是按照“application/x-www-form-urlencoded”的MIME類型的規(guī)則進(jìn)行編碼的。實(shí)現(xiàn)時(shí)可以直接使用此類方式進(jìn)行編碼,然后把編碼后的字符串中:加號(hào)+替換為%20,星號(hào)*替換為%2A%7E替換為波浪號(hào)~,即可得到上述規(guī)則描述的編碼字符串。

    3. 使用等號(hào)=連接URL編碼后的參數(shù)名和參數(shù)值:percentEncode(參數(shù)Key) + “=” + percentEncode(參數(shù)值)

    4. 使用與(&)號(hào)連接第c步URL編碼后的請求參數(shù)對,如Action=CreateToken&Format=JSON

      說明

      字符串中第一個(gè)參數(shù)名前面不需要&符號(hào)。

    5. 返回規(guī)范化的請求字符串。

    示例如下:

    String percentEncode(String value) throws UnsupportedEncodingException {
        return value != null ? URLEncoder.encode(value, URL_ENCODING)
                .replace("+", "%20")
                .replace("*", "%2A")
                .replace("%7E", "~") : null;
    }
    
    // 對參數(shù)Key排序
    String[] sortedKeys = queryParamsMap.keySet().toArray(new String[] {});
    Arrays.sort(sortedKeys);
    
    // 對排序的參數(shù)進(jìn)行編碼、拼接
    for (String key : sortedKeys) {
        canonicalizedQueryString.append("&")
                .append(percentEncode(key)).append("=")
                .append(percentEncode(queryParamsMap.get(key)));
    }
    queryString = canonicalizedQueryString.toString().substring(1);
    說明

    完整代碼實(shí)現(xiàn)請參見完整示例的canonicalizedQuery函數(shù)。

    構(gòu)造規(guī)范化的請求字符串:

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

  2. 構(gòu)造待簽名字符串。

    將HTTP請求的方法(GET)、URL編碼的URL路徑(/)、第1步獲取的規(guī)范化請求字符串使用與(&)符號(hào)連接成待簽名字符串:HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(queryString)

    構(gòu)造簽名字符串代碼示例:

    StringBuilder strBuilderSign = new StringBuilder();
    strBuilderSign.append(HTTPMethod);
    strBuilderSign.append("&");
    strBuilderSign.append(percentEncode(urlPath));
    strBuilderSign.append("&");
    strBuilderSign.append(percentEncode(queryString));
    
    stringToSign = strBuilderSign.toString();
    說明

    完整代碼實(shí)現(xiàn)請參見完整示例的createStringToSign函數(shù)。

    構(gòu)造的簽名字符串:

    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-28
  3. 計(jì)算簽名。

    • 簽名采用HMAC-SHA1算法 + Base64,編碼采用UTF-8

    • 根據(jù)AccessKey Secret,將第2步構(gòu)造的待簽名字符串使用HMAC-SHA1算法計(jì)算出對應(yīng)的數(shù)字簽名。其中,計(jì)算簽名時(shí)使用的AccessKey Secret必須在其后面增加一個(gè)與字符&

    • 簽名也要做URL編碼。

    計(jì)算簽名的代碼示例:

    signature = Base64( HMAC-SHA1(stringToSign, accessKeySecret + "&") );
    // 進(jìn)行URL編碼
    signature = percentEncode(signature)
    說明

    完整代碼實(shí)現(xiàn)請閱讀完整示例的sign函數(shù)。

    計(jì)算得到的簽名:

    # 簽名串
    AKIktdPUMCV12fTh667BLXeuCtg=
    # URL編碼后的結(jié)果
    AKIktdPUMCV12fTh667BLXeuCtg%3D

    計(jì)算簽名后,將簽名的鍵值對用符號(hào)=連接,并使用符號(hào)&添加到第1步獲取的請求字符串中,作為HTTP GET請求參數(shù),發(fā)送到服務(wù)端,獲取Token。

    String queryStringWithSign = "Signature=" + signature + "&" + queryString;

快速測試

您可以使用以下參數(shù)計(jì)算簽名,比較計(jì)算結(jié)果是否一致。

說明

AccessKey Id和AccessKey Secret沒有提供真實(shí)數(shù)據(jù),Timestamp是過期的時(shí)間,使用這些參數(shù)計(jì)算的簽名,獲取Token時(shí)會(huì)失敗,僅用于計(jì)算簽名測試對比。

  • AccessKeyId

    my_access_key_id

  • AccessKeySecret:

    my_access_key_secret

  • Timestamp:

    2019-04-18T08:32:31Z

  • SignatureNonce:

    b924c8c3-6d03-4c5d-ad36-d984d3116788

請求參數(shù)如下:

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

  1. 規(guī)范化請求字符串。

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

  2. 構(gòu)造待簽名字符串。

    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-28
  3. 計(jì)算得到簽名。

    hHq4yNsPitlfDJ2L0nQPdugdEzM=
    # URL編碼后的結(jié)果
    hHq4yNsPitlfDJ2L0nQPdugdEzM%3D
  4. 得到攜帶簽名的請求字符串。

    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-28
  5. 組合成HTTP請求鏈接。

    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-28
  6. 替換第5步獲取的HTTP請求鏈接,使用瀏覽器或者curl,獲取Token。

    curl "http://nls-meta.cn-shanghai.aliyuncs.com/?Signature=${您的簽名}&AccessKeyId=${您的AccessKey Id}&Action=CreateToken&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=${您的請求UUID}&SignatureVersion=1.0&Timestamp=${您的請求時(shí)間戳}&Version=2019-02-28"

完整示例

說明
  • 本文提供Java、Python語言示例代碼,您可根據(jù)協(xié)議和示例實(shí)現(xiàn)其他語言的客戶端程序。

  • 調(diào)用接口前,需配置環(huán)境變量,通過環(huán)境變量讀取訪問憑證。智能語音交互的AccessKey ID和AccessKey Secret的環(huán)境變量名:ALIYUN_AK_IDALIYUN_AK_SECRET

  • Java示例

    依賴文件:

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

    示例代碼:

    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;
        /**
         * 獲取時(shí)間戳
         * 必須符合ISO8601規(guī)范,并需要使用UTC時(shí)間,時(shí)區(qū)為+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);
        }
        /**
         * 獲取UUID
         */
        public static String getUniqueNonce() {
            UUID uuid = UUID.randomUUID();
            return uuid.toString();
        }
        /**
         * URL編碼
         * 使用UTF-8字符集按照RFC3986規(guī)則編碼請求參數(shù)和參數(shù)取值。
         */
        public static String percentEncode(String value) throws UnsupportedEncodingException {
            return value != null ? URLEncoder.encode(value, URL_ENCODING).replace("+", "%20")
                    .replace("*", "%2A").replace("%7E", "~") : null;
        }
        /***
         * 將參數(shù)排序后,進(jìn)行規(guī)范化設(shè)置,組合成請求字符串。
         * @param queryParamsMap   所有請求參數(shù)
         * @return 規(guī)范化的請求字符串
         */
        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("規(guī)范化后的請求參數(shù)串:" + queryString);
            } catch (UnsupportedEncodingException e) {
                System.out.println("UTF-8 encoding is not supported.");
                e.printStackTrace();
            }
            return queryString;
        }
        /***
         * 構(gòu)造簽名字符串
         * @param method       HTTP請求的方法
         * @param urlPath      HTTP請求的資源路徑
         * @param queryString  規(guī)范化的請求字符串
         * @return 簽名字符串
         */
        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("構(gòu)造的簽名字符串:" + stringToSign);
            } catch (UnsupportedEncodingException e) {
                System.out.println("UTF-8 encoding is not supported.");
                e.printStackTrace();
            }
            return stringToSign;
        }
        /***
         * 計(jì)算簽名
         * @param stringToSign      簽名字符串
         * @param accessKeySecret   阿里云AccessKey Secret加上與號(hào)&
         * @return 計(jì)算得到的簽名
         */
        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("計(jì)算的得到的簽名:" + signBase64);
                String signUrlEncode = percentEncode(signBase64);
                System.out.println("UrlEncode編碼后的簽名:" + 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());
            }
        }
        /***
         * 發(fā)送HTTP GET請求,獲取token和有效期時(shí)間戳。
         * @param queryString 請求參數(shù)
         */
        public static void processGETRequest(String queryString) {
            /**
             * 設(shè)置HTTP GET請求
             * 1. 使用HTTP協(xié)議
             * 2. Token服務(wù)域名:nls-meta.cn-shanghai.aliyuncs.com
             * 3. 請求路徑:/
             * 4. 設(shè)置請求參數(shù)
             */
            String url = "http://nls-meta.cn-shanghai.aliyuncs.com";
            url = url + "/";
            url = url + "?" + queryString;
            System.out.println("HTTP請求鏈接:" + 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("提交獲取Token請求失敗: " + result);
                    }
                }
                else {
                    System.err.println("提交獲取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));
            // 所有請求參數(shù)
            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.構(gòu)造規(guī)范化的請求字符串
             */
            String queryString = canonicalizedQuery(queryParamsMap);
            if (null == queryString) {
                System.out.println("構(gòu)造規(guī)范化的請求字符串失敗!");
                return;
            }
            /**
             * 2.構(gòu)造簽名字符串
             */
            String method = "GET";  // 發(fā)送請求的 HTTP 方法,GET
            String urlPath = "/";   // 請求路徑
            String stringToSign = createStringToSign(method, urlPath, queryString);
            if (null == stringToSign) {
                System.out.println("構(gòu)造簽名字符串失敗");
                return;
            }
            /**
             * 3.計(jì)算簽名
             */
            String signature = sign(stringToSign, accessKeySecret + "&");
            if (null == signature) {
                System.out.println("計(jì)算簽名失敗!");
                return;
            }
            /**
             * 4.將簽名加入到第1步獲取的請求字符串
             */
            String queryStringWithSign = "Signature=" + signature + "&" + queryString;
            System.out.println("帶有簽名的請求字符串:" + queryStringWithSign);
            /**
             * 5.發(fā)送HTTP GET請求,獲取token。
             */
            processGETRequest(queryStringWithSign);
            if (token != null) {
                System.out.println("獲取的Token:" + token + ", 有效期時(shí)間戳(秒):" + expireTime);
                // 將10位數(shù)的時(shí)間戳轉(zhuǎn)換為北京時(shí)間
                String expireDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(expireTime * 1000));
                System.out.println("Token有效期的北京時(shí)間:" + expireDate);
            }
        }
    }

  • Python示例

    說明

    • Python版本要求:Python3.4及以上。

    • 安裝Python HTTP庫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'}
            # 構(gòu)造規(guī)范化的請求字符串
            query_string = AccessToken._encode_dict(parameters)
            print('規(guī)范化的請求字符串: %s' % query_string)
            # 構(gòu)造待簽名字符串
            string_to_sign = 'GET' + '&' + AccessToken._encode_text('/') + '&' + AccessToken._encode_text(query_string)
            print('待簽名的字符串: %s' % string_to_sign)
            # 計(jì)算簽名
            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('簽名: %s' % signature)
            # 進(jìn)行URL編碼
            signature = AccessToken._encode_text(signature)
            print('URL編碼后的簽名: %s' % signature)
            # 調(diào)用服務(wù)
            full_url = 'http://nls-meta.cn-shanghai.aliyuncs.com/?Signature=%s&%s' % (signature, query_string)
            print('url: %s' % full_url)
            # 提交HTTP GET請求
            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__":
        # 用戶信息
        access_key_id = os.getenv('ALIYUN_AK_ID')
        access_key_secret = os.getenv('ALIYUN_AK_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('token有效期的北京時(shí)間:%s' % (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(expire_time))))

相關(guān)文檔

除了OpenAPI方式獲取Token,您還可以通過以下方式獲取Token: