OSS exige une signature V4 dans chaque requête PostObject pour en vérifier l'authenticité. Votre serveur d'application génère la signature à partir des paramètres de la requête (politique, expiration) en utilisant votre AccessKey Secret et l'algorithme HMAC-SHA256. OSS rejette toute requête dont la signature est invalide.
Fonctionnement des signatures POST
Les requêtes POST utilisent l'algorithme de signature V4. Le formulaire et la politique garantissent conjointement l'authenticité de la requête.
Éléments du formulaire
Un formulaire transmet le fichier et les métadonnées dans une requête POST. Le tableau suivant décrit les éléments spécifiques à la version V4. Les éléments courants sont répertoriés dans Éléments de formulaire PostObject.
Paramètre | Type | Obligatoire | Description |
x-oss-signature-version | String | Oui | Version de la signature et algorithme. La valeur est fixée à |
x-oss-credential | String | Oui | Spécifie l'ensemble de paramètres pour la clé dérivée. Le format est le suivant :
|
x-oss-date | String | Oui | Heure de la requête au format ISO 8601. Exemple :
|
x-oss-signature | String | Oui | Hachage HMAC-SHA256 de la politique encodée en Base64, représenté sous forme de chaîne hexadécimale. |
Politique
La politique est un objet JSON qui restreint les téléchargements de fichiers en spécifiant les noms de compartiment autorisés, les préfixes d'objet, les délais d'expiration, les méthodes HTTP, les tailles de contenu et les types de contenu.
Une politique doit inclure expiration et conditions. La condition x-oss-security-token de cet exemple n'est requise que lors de l'utilisation d'identifiants temporaires STS. Omettez-la si vous utilisez une AccessKey à long terme.
{
"expiration": "2023-12-03T13:00:00.000Z",
"conditions": [
{"bucket": "examplebucket"},
{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
{"x-oss-credential": "AKIDEXAMPLE/20231203/cn-hangzhou/oss/aliyun_v4_request"},
{"x-oss-security-token": "CAIS******"},
{"x-oss-date": "20231203T121212Z"},
["content-length-range", 1, 10],
["eq", "$success_action_status", "201"],
["starts-with", "$key", "user/eric/"],
["in", "$content-type", ["image/jpg", "image/png"]],
["not-in", "$cache-control", ["no-cache"]]
]
}
Les paramètres de la politique sont décrits ci-après :
-
expiration
Délai d'expiration de la politique au format ISO 8601 GMT. Exemple :
2023-12-03T13:00:00.000Zsignifie que la requête POST doit être envoyée avant 13:00:00 UTC le 3 décembre 2023. -
conditions
Définit les conditions applicables aux champs du formulaire dans la requête POST.
Paramètre
Type
Obligatoire
Description
Type de correspondance
bucket
String
Non
Nom du compartiment.
bucket
x-oss-signature-version
String
Oui
Version de la signature et algorithme. La valeur est fixée à
OSS4-HMAC-SHA256.x-oss-signature-version
x-oss-credential
String
Oui
Spécifie l'ensemble de paramètres pour la clé dérivée. Le format est le suivant :
<AccessKeyId>/<date>/<region>/oss/aliyun_v4_requestAccessKeyId: votre ID AccessKey.date: date de la requête.region: ID de région Alibaba Cloud standard. Exemple :cn-hangzhou.oss: nom du service demandé. La valeur est fixée àoss.aliyun_v4_request: version de la requête. La valeur est fixée àaliyun_v4_request.
x-oss-credential
x-oss-security-token
String
Non
Requis uniquement lors de l'utilisation d'identifiants temporaires STS. Obtenez un jeton en appelant l'opération AssumeRole.
x-oss-security-token
x-oss-date
String
Oui
Heure de la requête au format ISO 8601. Exemple :
20231203T121212Z.Un décalage horaire arrière de 15 minutes est autorisé pour l'en-tête
x-oss-dateafin de tenir compte des délais réseau et de la dérive des horloges.Une requête est valide pendant un maximum de 7 jours à compter de la valeur
x-oss-date. OSS rejette les requêtes dont la valeurx-oss-datea expiré pour prévenir les attaques par rejeu.La valeur
x-oss-datesert d'TimeStampdansStringToSign. Elle doit correspondre au même jour que laDatede la clé de signature et concorder avec la valeurx-oss-datede la politique.
x-oss-date
content-length-range
String
Non
Taille minimale et maximale autorisée de l'objet à télécharger, en octets.
content-length-range
success_action_status
String
Non
Code d'état HTTP à renvoyer après un téléchargement réussi.
eq, eq-ci, starts-with, starts-with-ci, in, in-ci, not-in, not-in-ci
key
String
Non
Nom de l'objet à télécharger.
eq, eq-ci, starts-with, starts-with-ci, in, in-ci, not-in, not-in-ci
content-type
String
Non
Restreint le type de fichier du téléchargement.
eq, eq-ci, starts-with, starts-with-ci, in, in-ci, not-in, not-in-ci
cache-control
String
Non
Spécifie le comportement de mise en cache de l'objet.
eq, eq-ci, starts-with, starts-with-ci, in, in-ci, not-in, not-in-ci
Processus de calcul de la signature
Créez une politique encodée en UTF-8.
-
Construisez la chaîne à signer.
Encodez la politique en Base64. Le résultat constitue la chaîne à signer.
-
Calculez la clé de signature.
Dérivez une clé de signature en appliquant des opérations HMAC-SHA256 successives à l'aide de votre AccessKey Secret, de la date, de la région et du nom du service.
-
Calculez la signature.
Signez la chaîne à signer avec la clé de signature via HMAC-SHA256, puis convertissez le résultat en une chaîne hexadécimale. Il s'agit de la signature finale.
Exemples de calcul de signature POST
-
L'exemple Java suivant calcule une signature POST pour la politique ci-dessus.
Identifiants AccessKey
import com.aliyun.oss.common.utils.BinaryUtil; import org.apache.commons.codec.binary.Base64; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Map; import java.util.HashMap; import java.util.List; import java.util.ArrayList; import java.util.Arrays; public class Demo { public static void main(String[] args) throws Exception { // Before you run this code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set. String accesskeyid = System.getenv().get("OSS_ACCESS_KEY_ID"); String accesskeysecret = System.getenv().get("OSS_ACCESS_KEY_SECRET"); // Step 1: Create a policy. ObjectMapper mapper = new ObjectMapper(); Map<String, Object> policy = new HashMap<>(); policy.put("expiration", "2024-12-03T13:00:00.000Z"); List<Object> conditions = new ArrayList<>(); Map<String, String> bucketCondition = new HashMap<>(); bucketCondition.put("bucket", "examplebucket"); conditions.add(bucketCondition); Map<String, String> signatureVersionCondition = new HashMap<>(); signatureVersionCondition.put("x-oss-signature-version", "OSS4-HMAC-SHA256"); conditions.add(signatureVersionCondition); Map<String, String> credentialCondition = new HashMap<>(); credentialCondition.put("x-oss-credential", accesskeyid + "/20241203/cn-hangzhou/oss/aliyun_v4_request"); conditions.add(credentialCondition); Map<String, String> dateCondition = new HashMap<>(); dateCondition.put("x-oss-date", "20241203T121212Z"); conditions.add(dateCondition); conditions.add(Arrays.asList("content-length-range", 1, 10)); conditions.add(Arrays.asList("eq", "$success_action_status", "201")); conditions.add(Arrays.asList("starts-with", "$key", "user/eric/")); conditions.add(Arrays.asList("in", "$content-type", Arrays.asList("image/jpg", "image/png"))); conditions.add(Arrays.asList("not-in", "$cache-control", Arrays.asList("no-cache"))); policy.put("conditions", conditions); String jsonPolicy = mapper.writeValueAsString(policy); // Step 2: Construct the string to sign. String stringToSign = new String(Base64.encodeBase64(jsonPolicy.getBytes())); System.out.println(stringToSign); // Step 3: Calculate the signing key. byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), "20241203"); byte[] dateRegionKey = hmacsha256(dateKey, "cn-hangzhou"); byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss"); byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request"); // Step 4: Calculate the signature. byte[] result = hmacsha256(signingKey, stringToSign); String signature = BinaryUtil.toHex(result); System.out.println("signature:" + signature); } public static byte[] hmacsha256(byte[] key, String data) { try { // Initialize the HMAC key specification, specifying HmacSHA256 as the algorithm and using the provided key. SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256"); // Get a Mac instance, specifying HmacSHA256 as the algorithm. Mac mac = Mac.getInstance("HmacSHA256"); // Initialize the Mac object with the key. mac.init(secretKeySpec); // Perform the HMAC calculation. The doFinal method takes the data and returns the resulting hash as a byte array. byte[] hmacBytes = mac.doFinal(data.getBytes()); return hmacBytes; } catch (Exception e) { throw new RuntimeException("Failed to calculate HMAC-SHA256", e); } } }Le résultat suivant est renvoyé :
signature:3908473f7dbfb79a102eaaa44ca1edec8d7058ce3bd1c624d59eb437463bd5d6Identifiants d'accès temporaires
Lors de l'utilisation d'identifiants temporaires provenant de STS, obtenez un jeton de sécurité en appelant l'opération AssumeRole.
import com.aliyun.oss.common.utils.BinaryUtil; import org.apache.commons.codec.binary.Base64; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import com.aliyun.sts20150401.models.AssumeRoleResponse; import com.aliyun.sts20150401.models.AssumeRoleResponseBody; import com.aliyun.tea.TeaException; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.*; public class Demo { // Initialize the STS client. public static com.aliyun.sts20150401.Client createStsClient() throws Exception { com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config() // Required. Make sure that the OSS_ACCESS_KEY_ID environment variable is set. .setAccessKeyId(System.getenv("OSS_ACCESS_KEY_ID")) // Required. Make sure that the OSS_ACCESS_KEY_SECRET environment variable is set. .setAccessKeySecret(System.getenv("OSS_ACCESS_KEY_SECRET")); // Endpoint config.endpoint = "sts.cn-hangzhou.aliyuncs.com"; return new com.aliyun.sts20150401.Client(config); } // Obtain temporary access credentials from STS. public static AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials getCredential() throws Exception { com.aliyun.sts20150401.Client client = Demo.createStsClient(); com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest() // Required. Make sure that the OSS_STS_ROLE_ARN environment variable is set. .setRoleArn(System.getenv("OSS_STS_ROLE_ARN")) .setRoleSessionName("role_session_name");// Custom session name. com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions(); try { // If you copy this code, print the API response on your own. AssumeRoleResponse response = client.assumeRoleWithOptions(assumeRoleRequest, runtime); // The credentials object contains the AccessKeyId, AccessKeySecret, and SecurityToken for subsequent operations. return response.body.credentials; } catch (TeaException error) { // This is for demonstration only. In a production environment, handle exceptions with care and do not ignore them. // Error message System.out.println(error.getMessage()); // Troubleshooting URL System.out.println(error.getData().get("Recommend")); com.aliyun.teautil.Common.assertAsString(error.message); } catch (Exception _error) { TeaException error = new TeaException(_error.getMessage(), _error); // This is for demonstration only. In a production environment, handle exceptions with care and do not ignore them. // Error message System.out.println(error.getMessage()); // Troubleshooting URL System.out.println(error.getData().get("Recommend")); com.aliyun.teautil.Common.assertAsString(error.message); } return null; } public static void main(String[] args) throws Exception { AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials sts_data = getCredential(); String accesskeyid = sts_data.accessKeyId; String accesskeysecret = sts_data.accessKeySecret; String securitytoken = sts_data.securityToken; // Step 1: Create a policy. ObjectMapper mapper = new ObjectMapper(); Map<String, Object> policy = new HashMap<>(); policy.put("expiration", "2024-12-03T13:00:00.000Z"); List<Object> conditions = new ArrayList<>(); Map<String, String> bucketCondition = new HashMap<>(); bucketCondition.put("bucket", "examplebucket"); conditions.add(bucketCondition); Map<String, String> signatureVersionCondition = new HashMap<>(); signatureVersionCondition.put("x-oss-signature-version", "OSS4-HMAC-SHA256"); conditions.add(signatureVersionCondition); Map<String, String> securityTokenCondition = new HashMap<>(); securityTokenCondition.put("x-oss-security-token", securitytoken); conditions.add(securityTokenCondition); Map<String, String> credentialCondition = new HashMap<>(); credentialCondition.put("x-oss-credential", accesskeyid + "/20241203/cn-hangzhou/oss/aliyun_v4_request"); conditions.add(credentialCondition); Map<String, String> dateCondition = new HashMap<>(); dateCondition.put("x-oss-date", "20241203T121212Z"); conditions.add(dateCondition); conditions.add(Arrays.asList("content-length-range", 1, 10)); conditions.add(Arrays.asList("eq", "$success_action_status", "201")); conditions.add(Arrays.asList("starts-with", "$key", "user/eric/")); conditions.add(Arrays.asList("in", "$content-type", Arrays.asList("image/jpg", "image/png"))); conditions.add(Arrays.asList("not-in", "$cache-control", Arrays.asList("no-cache"))); policy.put("conditions", conditions); String jsonPolicy = mapper.writeValueAsString(policy); // Step 2: Construct the string to sign. String stringToSign = new String(Base64.encodeBase64(jsonPolicy.getBytes())); // Step 3: Calculate the signing key. byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), "20241203"); byte[] dateRegionKey = hmacsha256(dateKey, "cn-hangzhou"); byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss"); byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request"); // Step 4: Calculate the signature. byte[] result = hmacsha256(signingKey, stringToSign); String signature = BinaryUtil.toHex(result); System.out.println("signature:" + signature); } public static byte[] hmacsha256(byte[] key, String data) { try { // Initialize the HMAC key specification, specifying HmacSHA256 as the algorithm and using the provided key. SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256"); // Get a Mac instance, specifying HmacSHA256 as the algorithm. Mac mac = Mac.getInstance("HmacSHA256"); // Initialize the Mac object with the key. mac.init(secretKeySpec); // Perform the HMAC calculation. The doFinal method takes the data and returns the resulting hash as a byte array. byte[] hmacBytes = mac.doFinal(data.getBytes()); return hmacBytes; } catch (Exception e) { throw new RuntimeException("Failed to calculate HMAC-SHA256", e); } } }Le résultat suivant est renvoyé :
signature:1e09438f7ad01af6b3e144b42c98929c68f8d090ce07f4c277b18d8b62d0aa02 -
L'exemple Python suivant calcule une signature POST.
import base64 import hmac import hashlib import os def hmac_sha256(key, data): return hmac.new(key, data.encode('utf-8'), hashlib.sha256).digest() # Read the AccessKey ID and AccessKey Secret from environment variables. accesskeyid = os.getenv('OSS_ACCESS_KEY_ID') accesskeysecret = os.getenv('OSS_ACCESS_KEY_SECRET') # Print the AccessKey ID. print(accesskeyid) # Check if the environment variables were successfully retrieved. if not accesskeyid or not accesskeysecret: raise ValueError("Necessary environment variables not found: OSS_ACCESS_KEY_ID or OSS_ACCESS_KEY_SECRET") # Create the policy. policy = f'''{{ "expiration": "2025-01-01T00:00:00.000Z", "conditions": [ {{"x-oss-signature-version": "OSS4-HMAC-SHA256"}}, {{"x-oss-credential": "{accesskeyid}/20241105/cn-hangzhou/oss/aliyun_v4_request"}}, {{"x-oss-date": "20241105T065000Z"}} ] }}''' # Print the policy. print(policy) # Calculate the string to sign. string_to_sign = base64.b64encode(policy.encode('utf-8')).decode('utf-8') print(string_to_sign) # Calculate the signing key. date_key = hmac_sha256(f"aliyun_v4{accesskeysecret}".encode('utf-8'), "20241105") date_region_key = hmac_sha256(date_key, "cn-hangzhou") date_region_service_key = hmac_sha256(date_region_key, "oss") signing_key = hmac_sha256(date_region_service_key, "aliyun_v4_request") # Calculate the signature. result = hmac_sha256(signing_key, string_to_sign) signature = result.hex() print("signature:", signature)Le résultat suivant est renvoyé :
signature:9e85d56429245283b1aca5bc2dc31e0020b95ac2de9e9b81b496994db602ba1e