通过SDK获取Token

更新时间:
复制 MD 格式

在服务端通过 SDK 获取 Token,可避免在移动端应用中保存长期 AccessKey。SDK 封装请求签名,应用负责保存 Token、检查有效期并在过期前重新获取。

背景信息

按项目使用的 SDK 选择一种获取方式,无需同时集成两种 SDK。

获取方式

适用场景

智能语音交互 SDK

已集成相应 SDK,使用封装的 Token 请求类。

阿里云公共 SDK

使用公共 SDK 调用 CreateToken,按项目语言选择示例。

配置访问凭证

准备已开通智能语音交互服务的账号及具有所需权限的 AccessKey ID 和 AccessKey Secret。服务开通和凭证准备方法,请参见快速开始。

获取 Token 使用的是 AccessKey,不是百炼 API Key。将 AccessKey 配置到运行示例的进程环境中:ALIYUN_AK_ID 对应 AccessKey ID,ALIYUN_AK_SECRET 对应 AccessKey Secret。

重要

AccessKey 仅保存在可信的服务端环境,不写入源代码或移动端应用。移动端调用语音服务前,先向业务服务端请求 Token。示例只输出获取结果和过期时间,不输出 Token 本身;不要将 AccessKey、Token 或带签名的完整请求写入日志。

通过智能语音交互 SDK 获取 Token

Java

添加 Maven 依赖。示例使用 nls-sdk-common 2.1.6;在 JDK 21 下运行时,还需添加 JAXB API 依赖。

<dependency>
    <groupId>com.alibaba.nls</groupId>
    <artifactId>nls-sdk-common</artifactId>
    <version>2.1.6</version>
</dependency>
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>

调用 apply() 发起请求,再读取 getToken() 和 getExpireTime()。此请求类不会自动定时刷新 Token。

import com.alibaba.nls.client.AccessToken;

public class NlsTokenDemo {
    public static void main(String[] args) throws Exception {
        AccessToken request = new AccessToken(
                System.getenv("ALIYUN_AK_ID"),
                System.getenv("ALIYUN_AK_SECRET"),
                "nls-meta.cn-shanghai.aliyuncs.com",
                "cn-shanghai", "2019-02-28");

        request.apply();
        String token = request.getToken();
        long expireTime = request.getExpireTime();
        System.out.println("Token acquired: " + (token != null && !token.isEmpty()));
        System.out.println("ExpireTime (Unix seconds): " + expireTime);
    }
}

C++

下载 C++ Token SDK并解压。该包包含头文件、示例以及 Linux 和 Windows 库。环境要求如下:

  • Linux:Glibc 2.5 及以上,GCC 4 或 GCC 5。

  • Windows:Visual Studio 2013 或 Visual Studio 2015,需自行创建工程并配置库引用。

将解压目录中的 include 加入头文件搜索路径,并配置对应平台的 SDK 和依赖库。Linux 库位于 lib/linux.tar.gz,需先解压。Linux 示例链接 alibabacloud-idst-common、jsoncpp、ssl、crypto、curl 和 uuid 库。例如,使用以下命令编译,并将 path/to/NlsCommonSdk 替换为实际解压路径:

g++ -D_GLIBCXX_USE_CXX11_ABI=0 tokenDemo.cpp \
  -I path/to/NlsCommonSdk/include \
  -L path/to/NlsCommonSdk/lib/linux \
  -lalibabacloud-idst-common -ljsoncpp -lssl -lcrypto -lcurl -luuid \
  -o tokenDemo

运行时将 path/to/NlsCommonSdk/lib/linux 加入 LD_LIBRARY_PATH,以便加载动态库。

以下代码从环境变量读取 AccessKey,不需要在命令行参数中传入密钥。

#include <cstdlib>
#include <iostream>
#include "Token.h"

int main() {
    const char* accessKeyId = std::getenv("ALIYUN_AK_ID");
    const char* accessKeySecret = std::getenv("ALIYUN_AK_SECRET");
    if (!accessKeyId || !accessKeySecret) {
        std::cerr << "Set ALIYUN_AK_ID and ALIYUN_AK_SECRET." << std::endl;
        return 1;
    }

    AlibabaNlsCommon::NlsToken request;
    request.setAccessKeyId(accessKeyId);
    request.setKeySecret(accessKeySecret);
    if (request.applyNlsToken() == -1) {
        std::cerr << request.getErrorMsg() << std::endl;
        return 1;
    }

    const char* token = request.getToken();
    unsigned int expireTime = request.getExpireTime();

    std::cout << "Token acquired: " << (token != NULL && token[0] != '\0') << std::endl;
    std::cout << "ExpireTime (Unix seconds): " << expireTime << std::endl;
    return 0;
}

通过阿里云公共 SDK 获取 Token

公共 SDK 的 RPC 请求使用以下参数。域名、地域和 API 版本需配套使用,不能只修改其中一项。

参数

配置值

说明

domain

nls-meta.cn-shanghai.aliyuncs.com

获取 Token 的域名。

region_id

cn-shanghai

请求地域。

action

CreateToken

接口名称。

version

2019-02-28

RPC API 版本。

Java

添加 Maven 依赖。示例使用 aliyun-java-sdk-core 3.7.1 和 fastjson 1.2.83;JDK 21 还需 JAXB API 2.3.1。

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>3.7.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;

public class CreateTokenDemo {
    public static void main(String[] args) throws Exception {
        DefaultProfile profile = DefaultProfile.getProfile(
                "cn-shanghai", System.getenv("ALIYUN_AK_ID"),
                System.getenv("ALIYUN_AK_SECRET"));
        DefaultAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setDomain("nls-meta.cn-shanghai.aliyuncs.com");
        request.setVersion("2019-02-28");
        request.setAction("CreateToken");
        request.setMethod(MethodType.POST);
        request.setProtocol(ProtocolType.HTTPS);

        CommonResponse response = client.getCommonResponse(request);
        JSONObject result = JSON.parseObject(response.getData()).getJSONObject("Token");
        String token = result.getString("Id");
        long expireTime = result.getLongValue("ExpireTime");
        System.out.println("Token acquired: " + (token != null && !token.isEmpty()));
        System.out.println("ExpireTime (Unix seconds): " + expireTime);
    }
}

Python

安装依赖。示例使用 aliyun-python-sdk-core 2.15.1。

pip install aliyun-python-sdk-core
import json
import os

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest

client = AcsClient(
    os.environ["ALIYUN_AK_ID"],
    os.environ["ALIYUN_AK_SECRET"],
    "cn-shanghai",
)

request = CommonRequest()
request.set_method("POST")
request.set_protocol_type("https")
request.set_domain("nls-meta.cn-shanghai.aliyuncs.com")
request.set_version("2019-02-28")
request.set_action_name("CreateToken")

result = json.loads(client.do_action_with_exception(request))
token = result["Token"]["Id"]
expire_time = result["Token"]["ExpireTime"]
print("Token acquired:", bool(token))
print("ExpireTime (Unix seconds):", expire_time)

Go

在 Go 模块中安装依赖。示例使用 alibaba-cloud-sdk-go 1.63.107。

go get github.com/aliyun/alibaba-cloud-sdk-go/sdk
package main

import (
    "encoding/json"
    "fmt"
    "os"

    "github.com/aliyun/alibaba-cloud-sdk-go/sdk"
    "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
    "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
)

func main() {
    credential := credentials.NewAccessKeyCredential(
        os.Getenv("ALIYUN_AK_ID"), os.Getenv("ALIYUN_AK_SECRET"))
    client, err := sdk.NewClientWithOptions("cn-shanghai", sdk.NewConfig(), credential)
    if err != nil {
        panic(err)
    }

    request := requests.NewCommonRequest()
    request.Scheme = "HTTPS"
    request.Method = "POST"
    request.Domain = "nls-meta.cn-shanghai.aliyuncs.com"
    request.ApiName = "CreateToken"
    request.Version = "2019-02-28"
    response, err := client.ProcessCommonRequest(request)
    if err != nil {
        panic(err)
    }

    var result struct {
        Token struct {
            Id string
            ExpireTime int64
        }
    }
    if err := json.Unmarshal(response.GetHttpContentBytes(), &result); err != nil {
        panic(err)
    }
    token := result.Token.Id
    fmt.Println("Token acquired:", token != "")
    fmt.Println("ExpireTime (Unix seconds):", result.Token.ExpireTime)
}

PHP

使用 PHP 7.2 及以上版本,并通过 Composer 安装依赖。示例使用 alibabacloud/sdk 1.8.2345 和 alibabacloud/client 1.5.32。

composer require alibabacloud/sdk

此示例使用 SDK 的 ROA 请求封装,API 版本为 2018-05-18,请求路径为 /pop/2018-05-18/tokens。该版本与 RPC 示例中的版本不同,不要混用两种请求形式的参数。

<?php
require __DIR__ . '/vendor/autoload.php';

use AlibabaCloud\Client\AlibabaCloud;

AlibabaCloud::accessKeyClient(
    getenv('ALIYUN_AK_ID'), getenv('ALIYUN_AK_SECRET'))
    ->regionId('cn-shanghai')
    ->asDefaultClient();

$response = AlibabaCloud::nlsCloudMeta()
    ->v20180518()
    ->createToken()
    ->scheme('https')
    ->request();

$token = $response['Token']['Id'];
$expireTime = $response['Token']['ExpireTime'];
echo 'Token acquired: ' . (!empty($token) ? 'true' : 'false') . PHP_EOL;
echo 'ExpireTime (Unix seconds): ' . $expireTime . PHP_EOL;

Node.js

安装依赖。示例使用 @alicloud/pop-core 1.8.0。

npm install @alicloud/pop-core
const { RPCClient } = require('@alicloud/pop-core');

const client = new RPCClient({
  accessKeyId: process.env.ALIYUN_AK_ID,
  accessKeySecret: process.env.ALIYUN_AK_SECRET,
  endpoint: 'https://nls-meta.cn-shanghai.aliyuncs.com',
  apiVersion: '2019-02-28',
});

async function main() {
  const result = await client.request('CreateToken', {}, { method: 'POST' });
  const token = result.Token.Id;
  const expireTime = result.Token.ExpireTime;
  console.log('Token acquired:', Boolean(token));
  console.log('ExpireTime (Unix seconds):', expireTime);
}

main().catch((error) => {
  console.error('CreateToken failed:', error.code || error.name);
  process.exitCode = 1;
});

返回值与使用建议

公共 SDK 请求成功后,从响应的 Token 对象读取以下字段;NLS Java 请求类通过对应方法返回这些值。

字段

类型

说明

Id

String

Token 字符串,用于后续语音服务请求。NLS Java 对应 getToken()。

ExpireTime

Long

过期时间的 Unix 时间戳,单位为秒。NLS Java 对应 getExpireTime()。

  • 缓存 Token 并在有效期内复用,不必在每次语音服务请求前重新获取。根据返回的 ExpireTime 判断有效期,在过期前重新获取并更新缓存,不使用固定时长代替返回值。

  • 在可信环境中,同一个 Token 可以供多个进程或应用使用。使用本页配置的端点获取 Token,不要混用上海和新加坡端点签发的 Token。

  • 将 Id 字符串传给语音服务,不传整个 JSON 响应、AccessKey 或其他字段。具体传递位置遵循相应语音接口的鉴权要求。

常见问题

获取 Token 失败时如何排查?

根据 SDK 返回的错误码区分原因,不将所有鉴权错误都归为 AccessKey 配对问题。

错误码

排查方法

InvalidAccessKeyId.NotFound

检查 AccessKey ID 是否正确、是否属于预期身份,以及复制时是否包含空格。

SignatureDoesNotMatch

检查 AccessKey ID 与 AccessKey Secret 是否配对,以及参与签名的参数是否被修改。使用公共 SDK 构造请求,避免自行拼装签名。

InvalidTimeStamp.Expired

检查发起请求的系统时间,确保与标准时间同步。此错误属于请求时间戳问题,不等同于已经获取的 Token 过期。

InvalidVersion

核对请求域名和 API 版本,并区分 RPC 与 ROA。PHP 示例的请求形式需与其 API 版本配套。

获取 Token 后,语音接口提示 Token 无效怎么办?

40000001 是语音服务调用阶段的鉴权错误。检查是否传入了实际 Token 字符串、是否遗漏鉴权参数、Token 是否已过期,以及 Token 的签发端点是否与所调用的语音服务匹配。相同错误码可能对应多种原因,应结合完整错误信息判断。

出现 Not supported proxy scheme 如何处理?

检查 http_proxy、https_proxy 及程序中设置的代理。代理地址需使用 SDK 支持的协议,并确保地址、端口和代理服务可用。如果当前网络不需要代理,移除相关配置后重试。

相关文档