在服务端通过 SDK 获取 Token,可避免在移动端应用中保存长期 AccessKey。SDK 封装请求签名,应用负责保存 Token、检查有效期并在过期前重新获取。
背景信息
按项目使用的 SDK 选择一种获取方式,无需同时集成两种 SDK。
|
获取方式 |
适用场景 |
|
智能语音交互 SDK |
已集成相应 SDK,使用封装的 Token 请求类。 |
|
阿里云公共 SDK |
使用公共 SDK 调用 |
配置访问凭证
准备已开通智能语音交互服务的账号及具有所需权限的 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 版本需配套使用,不能只修改其中一项。
|
参数 |
配置值 |
说明 |
|
|
|
获取 Token 的域名。 |
|
|
|
请求地域。 |
|
|
|
接口名称。 |
|
|
|
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 请求类通过对应方法返回这些值。
|
字段 |
类型 |
说明 |
|
|
String |
Token 字符串,用于后续语音服务请求。NLS Java 对应 |
|
|
Long |
过期时间的 Unix 时间戳,单位为秒。NLS Java 对应 |
缓存 Token 并在有效期内复用,不必在每次语音服务请求前重新获取。根据返回的
ExpireTime判断有效期,在过期前重新获取并更新缓存,不使用固定时长代替返回值。在可信环境中,同一个 Token 可以供多个进程或应用使用。使用本页配置的端点获取 Token,不要混用上海和新加坡端点签发的 Token。
将
Id字符串传给语音服务,不传整个 JSON 响应、AccessKey 或其他字段。具体传递位置遵循相应语音接口的鉴权要求。
常见问题
获取 Token 失败时如何排查?
根据 SDK 返回的错误码区分原因,不将所有鉴权错误都归为 AccessKey 配对问题。
|
错误码 |
排查方法 |
|
|
检查 AccessKey ID 是否正确、是否属于预期身份,以及复制时是否包含空格。 |
|
|
检查 AccessKey ID 与 AccessKey Secret 是否配对,以及参与签名的参数是否被修改。使用公共 SDK 构造请求,避免自行拼装签名。 |
|
|
检查发起请求的系统时间,确保与标准时间同步。此错误属于请求时间戳问题,不等同于已经获取的 Token 过期。 |
|
|
核对请求域名和 API 版本,并区分 RPC 与 ROA。PHP 示例的请求形式需与其 API 版本配套。 |
获取 Token 后,语音接口提示 Token 无效怎么办?
40000001 是语音服务调用阶段的鉴权错误。检查是否传入了实际 Token 字符串、是否遗漏鉴权参数、Token 是否已过期,以及 Token 的签发端点是否与所调用的语音服务匹配。相同错误码可能对应多种原因,应结合完整错误信息判断。
出现 Not supported proxy scheme 如何处理?
检查 http_proxy、https_proxy 及程序中设置的代理。代理地址需使用 SDK 支持的协议,并确保地址、端口和代理服务可用。如果当前网络不需要代理,移除相关配置后重试。
相关文档
临时调试时,通过控制台获取 Token,请参见通过控制台获取Token。
需要直接构造签名请求时,请参见通过OpenAPI获取Token。