全部产品
Search
文档中心

表格存储:用户密钥安全

更新时间:Apr 29, 2026

表格存储支持 V4 签名算法,通过派生密钥替代AccessKey Secret 直接参与身份验证,降低密钥泄露的影响范围。派生密钥仅对特定地域和产品当天有效,次日自动失效。

V4 签名工作原理

V4 签名用派生密钥替代AccessKey Secret 直接参与身份验证。派生密钥由AccessKey Secret、日期、地域和产品码四个要素通过 HMAC 计算链推导得出:

HMAC(HMAC(HMAC(AccessKey Secret, 日期), 地域), 产品码) → 派生密钥

正因如此,即使某个派生密钥泄露,影响也严格限制在特定日期、特定地域和特定产品范围内,不会波及同账号下其他地域或其他产品的资源。此外,派生密钥次日自动失效,无需手动撤销。

说明

使用 V4 签名的同时,建议将AccessKey配置为环境变量,避免硬编码在代码中,进一步降低密钥泄露风险。

请求流程

  1. 客户端使用 V4 签名算法,基于AccessKey计算生成派生密钥,并以派生密钥发起请求。

  2. 服务端接收请求后,使用派生密钥对调用方身份进行验证。

  3. 验证通过后,服务端处理请求并返回结果。

    说明

    验证未通过时,服务端拒绝客户端访问。

  4. 客户端接收服务端返回的处理结果。

示例代码

重要

表格存储 Java SDK 5.16.1 及以上版本支持 V4 签名功能。使用前请确认SDK版本满足要求。

使用AccessKey初始化

以下示例以阿里云账号或RAM用户的AccessKey为例介绍如何配置访问凭证。AccessKey 的获取方式,请参见 如何获取AccessKey 。

以下示例代码使用 V4 签名初始化 Tablestore Client,获取实例下的数据表列表并打印到控制台。

  • 示例 1(推荐):仅需提供 AccessKey,派生密钥由SDK自动计算和刷新,无需手动维护。

  • 示例 2:同时提供AccessKey与派生密钥(v4SigningAccessKey)。派生密钥次日自动失效,必须自行实现定时刷新机制,否则过期后将无法访问表格存储服务。

import com.alicloud.openservices.tablestore.SyncClient;
import com.alicloud.openservices.tablestore.core.ResourceManager;
import com.alicloud.openservices.tablestore.core.auth.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import static com.alicloud.openservices.tablestore.core.Constants.PRODUCT;
import static com.alicloud.openservices.tablestore.core.Constants.SIGNING_KEY_SIGN_METHOD;

public class InitClientV4 {
    public static void main(String[] args) {
        // yourRegion 填写您的实例所在地域,如 cn-hangzhou
        final String region = "yourRegion";
        // yourInstanceName 填写您的实例名称
        final String instanceName = "yourInstanceName";
        // yourEndpoint 填写您的实例访问地址
        final String endpoint = "yourEndpoint";
        // 获取系统变量里的 AccessKey ID 和 AccessKey Secret
        final String accessKeyId = System.getenv("TABLESTORE_ACCESS_KEY_ID");
        final String accessKeySecret = System.getenv("TABLESTORE_ACCESS_KEY_SECRET");

        {
            /**
             * 示例一:使用原始的accessKeyId,accessKeySecret -> 先构造{@link DefaultCredentials },再生成 {@link V4Credentials }
             */
            DefaultCredentials credentials = new DefaultCredentials(accessKeyId, accessKeySecret);
            V4Credentials credentialsV4 = V4Credentials.createByServiceCredentials(credentials, region);
            CredentialsProvider provider = new DefaultCredentialProvider(credentialsV4);

            /**
             * using {@link V4Credentials } initialize tableStore client
             */
            SyncClient client = new SyncClient(endpoint, provider, instanceName, null, new ResourceManager(null, null));

            // do something
            client.listTable().getTableNames().forEach(System.out::println);
            // shutdown tableStore client
            client.shutdown();
        }

        {
            /**
             * 示例二:直接使用accessKey与派生密钥 -> 直接构造{@link V4Credentials }
             */
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            String signDate = dateFormat.format(new Date()); // signDate格式如同"20230527"
            String v4SigningAccessKey = CalculateV4SigningKeyUtil.finalSigningKeyString(accessKeySecret, signDate, region, PRODUCT, SIGNING_KEY_SIGN_METHOD); // 派生密钥
            V4Credentials credentialsV4 = new V4Credentials(accessKeyId, v4SigningAccessKey, region, signDate);
            CredentialsProvider provider = new DefaultCredentialProvider(credentialsV4);

            /**
             * using {@link V4Credentials } initialize tableStore client
             */
            SyncClient client = new SyncClient(endpoint, provider, instanceName, null, new ResourceManager(null, null));

            // do something
            client.listTable().getTableNames().forEach(System.out::println);
            // shutdown tableStore client
            client.shutdown();
        }
    }
}

使用STS初始化

如何获取 STS 临时访问凭证,请参见 使用STS临时访问凭证访问表格存储 。

以下示例代码使用 V4 签名初始化 Tablestore Client,获取实例下的数据表列表并打印到控制台。

  • 示例 1(推荐):仅需提供 STS 临时访问凭证,派生密钥由SDK自动计算和刷新,无需手动维护。

  • 示例 2:同时提供 STS 临时访问凭证与派生密钥(v4SigningAccessKey)。派生密钥次日自动失效,必须自行实现定时刷新机制,否则过期后将无法访问表格存储服务。

import com.alicloud.openservices.tablestore.SyncClient;
import com.alicloud.openservices.tablestore.core.ResourceManager;
import com.alicloud.openservices.tablestore.core.auth.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import static com.alicloud.openservices.tablestore.core.Constants.PRODUCT;
import static com.alicloud.openservices.tablestore.core.Constants.SIGNING_KEY_SIGN_METHOD;

public class InitClientV4 {
    public static void main(String[] args) {
        // yourRegion 填写您的实例所在地域,如 cn-hangzhou
        final String region = "yourRegion";
        // yourInstanceName 填写您的实例名称
        final String instanceName = "yourInstanceName";
        // yourEndpoint 填写您的实例访问地址
        final String endpoint = "yourEndpoint";
        // 获取环境变量里的 STS AccessKey ID、STS AccessKey Secret 和 STS Token
        final String accessKeyId = System.getenv("TABLESTORE_ACCESS_KEY_ID");
        final String accessKeySecret = System.getenv("TABLESTORE_ACCESS_KEY_SECRET");
        final String securityToken = System.getenv("TABLESTORE_SESSION_TOKEN");

        {
            /**
             *  示例一:使用原始的accessKeyId,accessKeySecret,securityToken -> 先构造{@link DefaultCredentials },再生成 {@link V4Credentials }
             */
            DefaultCredentials credentials = new DefaultCredentials(accessKeyId, accessKeySecret, securityToken);
            V4Credentials credentialsV4 = V4Credentials.createByServiceCredentials(credentials, region);
            CredentialsProvider provider = new DefaultCredentialProvider(credentialsV4);

            /**
             * using {@link V4Credentials } initialize tableStore client
             */
            SyncClient client = new SyncClient(endpoint, provider, instanceName, null, new ResourceManager(null, null));

            // do something
            client.listTable().getTableNames().forEach(System.out::println);
            // shutdown tableStore client
            client.shutdown();
        }
        
        {
            /**
             * 示例二:直接使用accessKey与派生密钥 -> 直接构造{@link V4Credentials }
             */
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            String signDate = dateFormat.format(new Date());      // signDate格式如同"20230527"
            String v4SigningAccessKey = CalculateV4SigningKeyUtil.finalSigningKeyString(accessKeySecret, signDate, region, PRODUCT, SIGNING_KEY_SIGN_METHOD);
            V4Credentials credentialsV4 = new V4Credentials(accessKeyId, v4SigningAccessKey, securityToken, region, signDate);
            CredentialsProvider provider = new DefaultCredentialProvider(credentialsV4);

            /**
             * using {@link V4Credentials } initialize tableStore client
             */
            SyncClient client = new SyncClient(endpoint, provider, instanceName, null, new ResourceManager(null, null));

            // do something
            client.listTable().getTableNames().forEach(System.out::println);
            // shutdown tableStore client
            client.shutdown();
        }
    }
}