全部产品
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();
        }
    }
}