Table Store支援採用V4簽名演算法實現對使用者密鑰的保護。在使用者身分識別驗證過程中,使用由V4簽名演算法計算產生的衍生金鑰,而非實際的使用者密鑰,從而降低密鑰泄露所引發的影響範圍。如果衍生金鑰發生泄露,其影響局限於當天某個產品下的指定地區資源,不會波及其他產品的資源及其他地區的資源。此外,衍生金鑰將在第二天自動到期不可用。
背景資訊
V4簽名提供了一種新的身份認證方式。該簽名由阿里雲帳號或RAM使用者的AccessKey Secret、日期、地區和產品碼四個資訊通過特定方式計算得到的字串構成。
使用V4簽名後,如果某一個V4簽名被竊取,則該帳號下其他地區、其他產品不會受到影響,並且被竊取的V4簽名有效期間不超過一天。因此使用V4簽名可以保證使用者的帳號密鑰安全。
除了V4簽名功能外,在日常業務中使用使用者密鑰時,請務必妥善保管該密鑰。例如,在代碼中將密鑰配置為環境變數之後再使用。
請求流程
在用戶端使用V4簽名演算法對使用者密鑰進行計算產生衍生金鑰,並使用衍生金鑰發起請求。
服務端接收到請求時,使用衍生金鑰進行使用者身分識別驗證。
使用者身分識別驗證通過後,服務端處理請求並返回處理結果。
說明如果使用者身分識別驗證未通過,則服務端會拒絕用戶端訪問。
用戶端收到服務端返回的處理結果。
範例程式碼
Table StoreJava SDK從5.16.1版本開始支援V4簽名功能。使用V4簽名前,請確保您已使用支援該功能的SDK版本。
使用AccessKey初始化
此處以阿里雲帳號或RAM使用者的AccessKey為例為您介紹如何配置訪問憑證。AccessKey的擷取方式,請參見如何擷取AccessKey。
以下範例程式碼使用V4簽名初始化Tablestore Client,擷取執行個體下的資料表列表並列印到控制台。
在樣本1中,使用者僅需提供存取金鑰(AccessKey),由Tablestore SDK計算生產衍生金鑰。使用者無需手動維護衍生金鑰,當衍生金鑰到期後,Tablestore SDK將自動進行重新整理。
在樣本2中,使用者直接提供存取金鑰(AccessKey)與衍生金鑰(v4SigningAccessKey)。衍生金鑰在第二天將自動到期,使用者需要實現衍生金鑰的定時更新能力,否則將無法訪問Table Store服務。
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臨時訪問憑證訪問Table Store。
以下範例程式碼使用V4簽名初始化Tablestore Client,擷取執行個體下的資料表列表並列印到控制台。
在樣本1中,使用者僅需提供STS臨時訪問憑據,由Tablestore SDK計算生產衍生金鑰。使用者無需手動維護衍生金鑰,當衍生金鑰到期後,Tablestore SDK將自動進行重新整理。
在樣本2中,使用者直接提供STS臨時訪問憑據與衍生金鑰(v4SigningAccessKey)。衍生金鑰在第二天將自動到期,使用者需要實現衍生金鑰的定時更新能力,否則將無法訪問Table Store服務。
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();
}
}
}