除了通過HTTP要求標頭部的Authorization欄位進行簽名授權外,您還可以產生一個包含簽名和其他必要的請求資訊的預簽名URL。通過這種方式,您可以在不透露訪問憑證的情況下,授予第三方在特定有效期間內對OSS資源的存取權限。本文介紹如何使用V4簽名演算法實現在URL中包含簽名。
SDK簽名實現
OSS SDK已實現自動完成V4簽名。推薦採用OSS SDK的方式發起請求,可以免去手動簽名的過程。如果您想瞭解具體語言的簽名實現,請參考OSS SDK的代碼。OSS SDK簽名實現的檔案請參見下表。
SDK | 用戶端初始化樣本 | 簽名實現 |
Java | ||
PHP | ||
Node.js | ||
Browser.js | ||
Python | ||
Go | ||
C++ | ||
C |
URL簽名描述
URL簽名樣本
https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject?x-oss-additional-headers=host&x-oss-credential=<AccessKeyId>%2F20241203%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-date=20241203T034420Z&x-oss-expires=86400&x-oss-signature=70c542eaf652ac291c0c343d63ac24ede41c0526661d9d4c63c0906a2686160c&x-oss-signature-version=OSS4-HMAC-SHA256
上述URL中的
x-oss-credential
的值為方便展示各個欄位的參數,使用正斜線(/)進行分隔。在實際請求時,需要對URL中的/
執行UrlEncode,即轉化成%2F
,樣本如下:&x-oss-credential=<AccessKeyId>%2F20241203%2Fcn-hangzhou%2Foss%2Faliyun_v4_request
URL中的QueryString參數說明
參數
類型
是否必選
樣本值
說明
x-oss-signature-version
字串
是
OSS4-HMAC-SHA256
指定簽名的版本和演算法,固定值為OSS4-HMAC-SHA256。
x-oss-credential
字串
是
LTAI********************/20241203/cn-hangzhou/oss/aliyun_v4_request
指明衍生金鑰的參數集,格式如下:
<AccessKeyId>/<date>/<region>/oss/aliyun_v4_request
AccessKeyId:填寫存取金鑰中的AccessKey ID。
date:填寫請求的日期,
region:填寫請求所在的Region。
oss:請求的服務名稱,固定為oss。
aliyun_v4_request:請求的版本說明,固定為aliyun_v4_request。
x-oss-date
字串
是
20241203T034420Z
簽名URL的起始時間,為避免時鐘誤差,允許向後位移15分鐘,格式為ISO8601。
說明該時間用作StringToSign中的TimeStamp,取值必須與建立SigningKey中的Date是同一天。
x-oss-expires
整數
是
3600
簽名URL的有效時間長度,單位為秒(s)。最小值為1,最大值為 604800(即7 天)。
x-oss-additional-headers
字串
否
host
除預設要加入簽名的Header以外,指定其他也需要簽名的Header。例如:添加簽名host,並禁止修改請求的網域名稱。
該欄位的構建方法說明如下:
額外頭部中的所有Header均要求小寫。
按照字典序升序排列額外頭部中的所有Header。
以分號串連數組中的元素,擷取字串。
x-oss-signature
字串
是
77Dv****************
用於簽名認證的描述資訊。x-oss-signature不參與簽名計算。
x-oss-security-token
字串
否
CAIS********************************
STS安全性權杖。僅當使用STS構造URL簽名時,才需要設定此參數。
簽名計算過程
URL簽名計算方法與Header簽名計算方法基本類似。但由於簽名URL使用方法的不同,與Header簽名計算仍存在以下差異:
簽名URL的方式不包含描述payload的Header(
x-oss-content-sha256
)。原因是建立預簽名時,無法預估實際傳輸的payload。因此,在URL簽名過程中,直接使用UNSIGNED-PAYLOAD。如果簽名URL的QueryParameter與待簽名Header中的Key相同但Value不同的情況,會出現報錯。同一個Key有多個Value的情況,會同時比較Key對應的所有Value,如果Value不一致也會出現報錯。
簽名URL中,如果通過STS訪問OSS,必須在QueryString中添加x-oss-security-token。
QueryString中的x-oss-signature不參與簽名。
步驟1:構造CanonicalRequest
步驟2:構造待簽名字串(StringToSign)
步驟3:計算Signature
簽名計算樣本
以建立一個預簽名URL,分享給其他使用者上傳資料為例,示範如何在URL包含V4簽名。
計算參數樣本
參數
值
AccessKeyId
accesskeyid
AccessKeySecret
accesskeysecret
Bucket
examplebucket
Object
exampleobject
Region
cn-hangzhou
GetObject
https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject?x-oss-additional-headers=host&x-oss-credential=<AccessKeyId>%2F20241203%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-date=20241203T032307Z&x-oss-expires=86400&x-oss-signature=eee300fa39f52127a02af5f9bb86c0fd8b6776fc19101d9a6a7982c9d0edcc04&x-oss-signature-version=OSS4-HMAC-SHA256 host:examplebucket.oss-cn-hangzhou.aliyuncs.com
在URL包含V4簽名的步驟如下:
構造CanonicalRequest。
String resourcePath = "exampleobject"; String endpoint = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com"; String queryString = "x-oss-additional-headers=host&" + "x-oss-credential=" + accesskeyid + "%2F" + dateStr + "%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&" + "x-oss-date=" + dateTimeStr + "&" + "x-oss-expires=86400&" + "x-oss-signature=" + signature + "&" + "x-oss-signature-version=OSS4-HMAC-SHA256"; String urlStr = endpoint + "/" + resourcePath + "?" + queryString; URL url = new URL(urlStr);
構造待簽名字串(StringToSign)。
String stringToSign = "OSS4-HMAC-SHA256\n" + dateTimeStr + "\n" + dateStr + "/cn-hangzhou/oss/aliyun_v4_request\n" + DigestUtils.sha256Hex(canonicalRequest);
計算簽名。
計算SigningKey。
說明為方便可讀,如下為SigningKey經Base64編碼後的字串。
dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), dateStr); dateRegionKey = hmacsha256(dateKey, "cn-hangzhou"); dateRegionServiceKey = hmacsha256(dateRegionKey, "oss"); signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request");
計算Signature。
result = hmacsha256(signingKey, stringToSign); String signature = BinaryUtil.toHex(result); signature:eee300fa39f52127a02af5f9bb86c0fd8b6776fc19101d9a6a7982c9d0edcc04
在URL中加入簽名。
String resourcePath = "exampleobject"; String endpoint = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com"; String queryString = "x-oss-additional-headers=host&" + "x-oss-credential=" + accesskeyid + "%2F" + dateStr + "%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&" + "x-oss-date=" + dateTimeStr + "&" + "x-oss-expires=86400&" + "x-oss-signature=" + signature + "&" + "x-oss-signature-version=OSS4-HMAC-SHA256"; String urlStr = endpoint + "/" + resourcePath + "?" + queryString; URL url = new URL(urlStr); System.out.println("url:" + url);
簽名計算完整範例程式碼
使用上述計算參數樣本,通過Java範例程式碼示範簽名計算的完整過程。
此樣本僅供示範URL計算簽名。如需使用此樣本,請將樣本參數替換為您所需參數,如:請將Bucket路徑替換為您的Bucket路徑;地區Region的取值為cn-hangzhou替換為您所需地區。
import com.aliyun.oss.common.utils.BinaryUtil;
import org.apache.commons.codec.digest.DigestUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;
public class Demo {
/**
* 簽名計算工具
*
* @return url
*/
public static void main(String[] args) throws Exception {
// 運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
String accesskeyid = System.getenv().get("OSS_ACCESS_KEY_ID");
String accesskeysecret = System.getenv().get("OSS_ACCESS_KEY_SECRET");
// 擷取目前時間並格式化為指定的 ISO8601 格式
ZonedDateTime now = ZonedDateTime.now(TimeZone.getTimeZone("UTC").toZoneId());
String dateStr = now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
String dateTimeStr = now.format(DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'"));
// 步驟1:構造CanonicalRequest。
String canonicalRequest =
"GET\n" +
"/examplebucket/exampleobject\n" +
"x-oss-additional-headers=host&x-oss-credential=" + accesskeyid + "%2F" + dateStr + "%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-date=" + dateTimeStr + "&x-oss-expires=86400&x-oss-signature-version=OSS4-HMAC-SHA256\n" +
"host:examplebucket.oss-cn-hangzhou.aliyuncs.com\n" +
"\n" +
"host\n" +
"UNSIGNED-PAYLOAD";
System.out.println("canonicalRequest:" + canonicalRequest);
// 步驟2:構造待簽名字串(StringToSign)。
String stringToSign = "OSS4-HMAC-SHA256\n" +
dateTimeStr + "\n" +
dateStr + "/cn-hangzhou/oss/aliyun_v4_request\n" +
DigestUtils.sha256Hex(canonicalRequest);
// 步驟3:計算Signature。
byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), dateStr);
byte[] dateRegionKey = hmacsha256(dateKey, "cn-hangzhou");
byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss");
byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request");
byte[] result = hmacsha256(signingKey, stringToSign);
String signature = BinaryUtil.toHex(result);
System.out.println("signature:" + signature);
// 步驟4:在URL中加入簽名。
String resourcePath = "exampleobject";
String endpoint = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com";
String queryString = "x-oss-additional-headers=host&" +
"x-oss-credential=" + accesskeyid + "%2F" + dateStr + "%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&" +
"x-oss-date=" + dateTimeStr + "&" +
"x-oss-expires=86400&" +
"x-oss-signature=" + signature + "&" +
"x-oss-signature-version=OSS4-HMAC-SHA256";
String urlStr = endpoint + "/" + resourcePath + "?" + queryString;
URL url = new URL(urlStr);
System.out.println("url:" + url);
}
public static byte[] hmacsha256(byte[] key, String data) {
try {
// 初始化HMAC密鑰規格,指定演算法為HMAC-SHA256並使用提供的密鑰。
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
// 擷取Mac執行個體,並通過getInstance方法指定使用HMAC-SHA256演算法。
Mac mac = Mac.getInstance("HmacSHA256");
// 使用密鑰初始化Mac對象。
mac.init(secretKeySpec);
// 執行HMAC計算,通過doFinal方法接收需要計算的資料並返回計算結果的數組。
byte[] hmacBytes = mac.doFinal(data.getBytes());
return hmacBytes;
} catch (Exception e) {
throw new RuntimeException("Failed to calculate HMAC-SHA256", e);
}
}
}
返回結果如下:
signature:eee300fa39f52127a02af5f9bb86c0fd8b6776fc19101d9a6a7982c9d0edcc04
url:https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject?x-oss-additional-headers=host&x-oss-credential=<AccessKeyId>%2F20241203%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-date=20241203T032307Z&x-oss-expires=86400&x-oss-signature=eee300fa39f52127a02af5f9bb86c0fd8b6776fc19101d9a6a7982c9d0edcc04&x-oss-signature-version=OSS4-HMAC-SHA256
當產生URL簽名的檔案類型為.txt時,線上預覽可能會出現亂碼問題。具體操作,請參見線上預覽.txt檔案出現亂碼問題。
常見SDK的自動產生簽名URL並使用簽名URL下載檔案的更多資訊,請參見使用簽名URL下載檔案。