L'opération PostObject vous permet de charger des fichiers directement depuis un client web vers Object Storage Service (OSS). Elle utilise une signature générée par le serveur pour garantir la sécurité et vous permet de configurer une politique afin de restreindre les chargements selon vos besoins métier.
Présentation de la solution
Pour mettre en œuvre le chargement direct avec signature côté serveur, suivez ces trois étapes :
L'utilisation d'identifiants d'accès temporaires évite d'exposer la clé à long terme de votre serveur, ce qui renforce la sécurité du chargement des fichiers.
Configurez OSS : Créez un bucket dans la console pour stocker les fichiers des utilisateurs. Configurez ensuite les règles Cross-Origin Resource Sharing (CORS) pour le bucket afin d'autoriser les requêtes cross-origin depuis le client web.
Configurez le serveur : Appelez Security Token Service (STS) pour obtenir des identifiants d'accès temporaires. Utilisez ensuite ces identifiants et une politique de chargement côté serveur pour générer une signature. Cette politique inclut des paramètres tels que le nom du bucket, le chemin du répertoire et l'heure d'expiration. Cette signature autorise un utilisateur à charger des fichiers pendant une période spécifiée.
Configurez le client web : Construisez une requête de formulaire HTML et utilisez la signature pour charger le fichier vers OSS.
Exemples de projets
Pour l'exemple de projet Java, consultez server-signed-direct-upload-java.zip.
Pour l'exemple de projet Python, consultez server-signed-direct-upload-python.zip.
Pour l'exemple de projet Node.js, consultez server-signed-direct-upload-nodejs.zip.
Pour l'exemple de projet Go, consultez server-signed-direct-upload-go.zip.
Pour l'exemple de projet PHP, consultez server-signed-direct-upload-php.zip.
Étapes
Étape 1 : Configurer OSS
Créer un bucket
Créez un bucket OSS pour stocker les fichiers chargés directement depuis un navigateur web.
Connectez-vous à la console OSS.
Dans le volet de navigation de gauche, cliquez sur Buckets, puis cliquez sur Create Bucket.
-
Dans le panneau Create Bucket, sélectionnez Quick Create et configurez les paramètres suivants :
Paramètre
Valeur d’exemple
Bucket Name
web-direct-upload
Region
China (Hangzhou)
Cliquez sur Create.
Configurer une règle CORS
Configurez une règle CORS pour votre bucket OSS.
Sur la page Buckets, cliquez sur le bucket cible.
Sur la page CORS, cliquez sur Create Rule.
-
Dans le panneau Create Rule, définissez les paramètres suivants.
Paramètre
Valeur d’exemple
Origin
*
Allowed Methods
POST, PUT, GET
Allowed Headers
*
Cliquez sur OK.
Étape 2 : Configurer le serveur
Pour un déploiement en production, si vous disposez déjà d’un serveur, ignorez les préparatifs et accédez directement à 1. Configurer les autorisations utilisateur.
Créer une instance ECS
Étape 1 : Créer une instance ECS
Accédez à la page Custom Launch et sélectionnez les ressources de base nécessaires à la création d’une instance ECS.
-
Sélectionner une région et une méthode de facturation
Choisissez une méthode de facturation adaptée à vos besoins métier. Ce tutoriel utilise le mode pay-as-you-go pour sa flexibilité.
-
En général, choisir une région proche de vos utilisateurs réduit la latence réseau et accélère l’accès. Ce tutoriel prend pour exemple la région China (Hangzhou).
Pour Billing Method, sélectionnez pay-as-you-go (post-payé et à la demande). Les instances pay-as-you-go ne prennent pas en charge le dépôt ICP. Une fois l’instance créée, sa région ne peut plus être modifiée. Les instances situées dans différentes régions ne peuvent pas communiquer via le réseau interne.
-
Créer un Virtual Private Cloud (VPC) et un vSwitch
Lors de la création d’un VPC, sélectionnez la même région que celle de l’instance ECS et planifiez les blocs CIDR selon vos besoins métier. Ce tutoriel illustre la création d’un VPC et d’un vSwitch dans la région China (Hangzhou). Après avoir créé le VPC et le vSwitch, revenez à la page d’achat ECS, actualisez-la et sélectionnez-les.
RemarqueVous pouvez créer un vSwitch lors de la création d’un VPC.
Sur la page Create VPC, définissez Name sur ProjectA-VPC, sélectionnez Manually Specify IPv4 CIDR Block pour IPv4 CIDR Block et saisissez
192.168.0.0/16, puis sélectionnez Do Not Assign pour IPv6 CIDR Block.Exemple de configuration du vSwitch : définissez Name sur ProjectA-vSwitch, sélectionnez Hangzhou Zone H pour Zone, définissez le bloc CIDR IPv4 sur
192.168.10.0/24, puis cliquez sur OK.
-
Sélectionner un type d’instance et une image
Sélectionnez un type d’instance et une image. L’image détermine le système d’exploitation et la version installés sur l’instance. Ce tutoriel utilise le type d’instance
ecs.e-c1m1.large, qui est économique et répond aux exigences des tests. L’image est l’image publiqueAlibaba Cloud Linux 3.2104 LTS 64-bit.
-
Configurer le stockage
Pour le système web simple présenté dans ce tutoriel, un disque système suffit pour le système d’exploitation ; aucun disque de données n’est donc requis.
Pour le disque système, sélectionnez ESSD, définissez Performance Level sur PL0 et Capacity sur 40 GiB, sélectionnez Release with Instance et n’ajoutez pas de disque de données.
-
Attribuer une adresse IP publique
Par souci de simplicité, ce tutoriel attribue directement une adresse IP publique à l’instance. Vous pouvez également associer une Elastic IP Address (EIP) à l’instance après sa création. Pour plus d’informations, consultez Associer une EIP à une ressource cloud.
RemarqueSi aucune adresse IP publique n’est attribuée, vous ne pouvez pas accéder directement à l’instance depuis Internet via SSH ou Remote Desktop Protocol (RDP), ni vérifier le déploiement du service web sur l’instance.
Ce tutoriel utilise la méthode de facturation de la bande passante pay-by-traffic. Cette méthode vous facture uniquement le trafic public consommé. Pour plus d’informations, consultez Facturation de la bande passante publique.
Définissez Peak bandwidth sur 5 Mbps.
-
Créer un groupe de sécurité
Créez un groupe de sécurité pour l’instance. Un groupe de sécurité est un pare-feu virtuel qui contrôle le trafic entrant et sortant d’une instance ECS. Lors de la création du groupe de sécurité, autorisez le trafic sur les ports suivants afin de pouvoir accéder ultérieurement à l’instance ECS.
Port range : SSH (22), RDP (3389), HTTP (80) et HTTPS (443).
RemarqueLes ports sélectionnés pour Port range sont requis par les applications exécutées sur l’instance ECS.
Par défaut, le groupe de sécurité créé ici inclut une règle qui définit la source sur 0.0.0.0/0. Cela permet l’accès depuis n’importe quelle adresse IP aux ports spécifiés. Si vous connaissez les adresses IP des clients demandeurs, nous vous recommandons de restreindre ultérieurement la source à une plage d’adresses IP spécifique. Pour plus d’informations, consultez Modifier une règle de groupe de sécurité.
Dans la section Security group type, sélectionnez Basic security group.
-
Créer une paire de clés
Une paire de clés fournit des identifiants de connexion sécurisés. Après avoir créé une paire de clés, vous devez télécharger sa clé privée, requise pour se connecter à une instance ECS. Ensuite, revenez à la page d’achat ECS, actualisez-la et sélectionnez la paire de clés.
-
L’utilisateur
rootdispose des privilèges les plus élevés dans le système d’exploitation, et l’utilisation derootcomme nom de connexion peut présenter des risques de sécurité. Nous vous recommandons d’utiliserecs-usercomme nom de connexion.RemarqueAprès la création d’une paire de clés, la clé privée est automatiquement téléchargée. Enregistrez le fichier de clé privée
.pemà partir de l’historique de téléchargement de votre navigateur.Dans la section Logon Credential, sélectionnez l’onglet Key pair, cliquez sur Create key pair. Ensuite, sélectionnez la paire de clés nouvellement créée (par exemple,
ecs-test) dans la liste déroulante Key pair.
-
Créer et afficher l’instance ECS
Après avoir sélectionné les ressources requises pour l’instance ECS, cliquez sur Create order. Dans la boîte de dialogue de succès, cliquez sur Management console pour afficher la nouvelle instance. Enregistrez les informations suivantes pour une utilisation ultérieure :
Instance ID : utilisé pour retrouver l’instance dans la liste des instances.
Region : utilisé pour retrouver l’instance dans la liste des instances.
Public IP address : utilisé pour vérifier le déploiement du service web.
Étape 2 : Se connecter à l’instance ECS
Sur la page Instances de la console ECS, retrouvez votre instance à l’aide de sa région et de son ID, puis dans la colonne Actions, cliquez sur Connect.
Dans la boîte de dialogue Remote connection, cliquez sur Sign in now à côté de Workbench.
Dans la boîte de dialogue Log on to instance, sélectionnez Terminal connection pour Connection method et SSH key authentication pour Authentication method. Ensuite, saisissez ou téléchargez votre fichier de clé privée, puis cliquez sur Log on pour vous connecter en tant qu’utilisateur
ecs-user.-
Remarque
Le fichier de clé privée (
.pem) est automatiquement téléchargé sur votre appareil lors de la création de la paire de clés. Consultez l’historique de téléchargement de votre navigateur pour localiser le fichier. -
Lorsque la sortie suivante s’affiche, vous êtes connecté avec succès à l’instance ECS.
Welcome to Alibaba Cloud Elastic Compute Service ! Last login: Sun Sep 29 15:35:22 2024 from xxx [ecs-user@iz*** ~]$
Autorisations utilisateur
Pour éviter les échecs de chargement OSS après le déploiement dus à des autorisations insuffisantes, créez un utilisateur RAM et configurez les autorisations requises.
Étape 1 : Créer un utilisateur RAM
Créez un utilisateur RAM et obtenez sa paire AccessKey pour servir d’identifiants à long terme pour votre serveur d’application.
Connectez-vous à la console RAM avec votre compte Alibaba Cloud ou en tant qu’administrateur RAM.
Dans le volet de navigation de gauche, choisissez Identities > Users.
Cliquez sur Create User.
Saisissez un Logon Name et un Display Name.
Dans la section Access Mode, sélectionnez Programmatic access, puis cliquez sur OK.
Le secret AccessKey n’est affiché qu’à la création et ne peut pas être récupéré ultérieurement. Conservez-le en toute sécurité.
Dans la colonne Actions, cliquez sur Copy pour enregistrer la paire AccessKey (AccessKey ID et AccessKey secret).
Étape 2 : Accorder l’autorisation AssumeRole
Après avoir créé l’utilisateur RAM, accordez-lui l’autorisation d’appeler l’opération STS AssumeRole. Cela permet à l’utilisateur d’obtenir des identifiants temporaires en endossant un rôle RAM.
Dans le volet de navigation de gauche, choisissez Identities > Users.
Sur la page Users, recherchez l’utilisateur RAM cible, puis cliquez sur Add Permissions dans la colonne Actions.
-
Sur la page Grant Permission, sélectionnez la stratégie système AliyunSTSAssumeRoleAccess.
RemarqueLa stratégie AliyunSTSAssumeRoleAccess accorde l’autorisation d’appeler l’opération
AssumeRole. Elle n’accorde pas d’autorisations pour les opérations ultérieures utilisant les identifiants temporaires, telles que les requêtes OSS. Cliquez sur OK.
Étape 3 : Créer un rôle RAM
Créez un rôle RAM pour le compte Alibaba Cloud actuel et obtenez son Alibaba Cloud Resource Name (ARN). L’utilisateur RAM endossera ce rôle.
Dans le volet de navigation de gauche, choisissez Identities > Roles.
Cliquez sur Create Role. Pour Principal Type, sélectionnez Alibaba Cloud Account.
Sélectionnez le compte Alibaba Cloud actuel et cliquez sur OK.
Saisissez un nom de rôle et cliquez sur OK.
Sur la page des détails du rôle RAM, cliquez sur Copy pour enregistrer l’ARN du rôle.
Étape 4 : Créer une politique de chargement de fichiers
Conformément au principe du moindre privilège, créez une Custom Policy pour le rôle RAM qui restreint les chargements à un bucket OSS spécifique.
Dans le volet de navigation de gauche, choisissez Permissions > Policies.
Cliquez sur Create Policy.
-
Sur la page Create Policy, cliquez sur JSON Editor et remplacez
<Bucket name>dans le script par le nom du bucketweb-direct-uploadque vous avez créé dans la section Preparations.{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": "oss:PutObject", "Resource": "acs:oss:*:*:<BucketName>/*" } ] } Après avoir configuré la politique, cliquez sur OK.
Dans la boîte de dialogue Create Policy, saisissez un Policy Name et cliquez sur OK.
Dans le volet de navigation de gauche, sélectionnez Identities > Roles.
Sur la page Roles, localisez le rôle RAM cible, puis cliquez sur Add Permissions dans la colonne Actions.
Sur la page Grant Permission, sélectionnez Custom Policy, puis choisissez la stratégie que vous avez créée.
Cliquez sur OK.
-
Depuis la ligne de commande, exécutez les commandes suivantes pour ajouter les paramètres des variables d'environnement au fichier
~/.bashrc.echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.bashrc echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.bashrc echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.bashrc -
Exécutez la commande suivante pour appliquer les modifications.
source ~/.bashrc -
Exécutez les commandes suivantes pour vérifier que les variables d'environnement sont correctement définies.
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN -
Dans le terminal, exécutez la commande suivante pour vérifier votre shell par défaut.
echo $SHELL -
Suivez les instructions correspondant à votre shell par défaut.
Zsh
-
Exécutez les commandes suivantes pour ajouter les paramètres des variables d'environnement au fichier
~/.zshrc.echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.zshrc echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.zshrc echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.zshrc -
Exécutez la commande suivante pour appliquer les modifications.
source ~/.zshrc -
Exécutez les commandes suivantes pour vérifier que les variables d'environnement sont correctement définies.
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
Bash
-
Exécutez les commandes suivantes pour ajouter les paramètres des variables d'environnement au fichier
~/.bash_profile.echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.bash_profile echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.bash_profile echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.bash_profile -
Exécutez la commande suivante pour appliquer les modifications.
source ~/.bash_profile -
Exécutez les commandes suivantes pour vérifier que les variables d'environnement sont correctement définies.
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
-
-
Exécutez les commandes suivantes dans l'invite de commandes (CMD).
setx OSS_ACCESS_KEY_ID "your-access-key-id" setx OSS_ACCESS_KEY_SECRET "your-access-key-secret" setx OSS_STS_ROLE_ARN "your-role-arn" Ouvrez une nouvelle fenêtre CMD.
-
Dans la nouvelle fenêtre CMD, exécutez les commandes suivantes pour vérifier que les variables d'environnement sont correctement définies.
echo %OSS_ACCESS_KEY_ID% echo %OSS_ACCESS_KEY_SECRET% echo %OSS_STS_ROLE_ARN% La requête de formulaire inclut le contenu du fichier et les paramètres renvoyés par le serveur d'application.
Avec cette requête, le client web communique directement avec OSS pour télécharger le fichier.
À l'exception du champ de formulaire de fichier, tous les autres champs de formulaire, y compris key, ne doivent pas dépasser 8 Ko.
Par défaut, les téléchargements via le web écrasent les objets portant le même nom. Pour éviter l'écrasement des objets, ajoutez le champ de formulaire x-oss-forbid-overwrite à la requête et définissez sa valeur sur true. Si un objet portant le même nom existe déjà dans OSS, le téléchargement échoue et OSS renvoie une erreur FileAlreadyExists.
Le formulaire HTML contient un champ de saisie de fichier et un bouton d'envoi.
Lorsque le formulaire est soumis, le code JavaScript empêche la soumission par défaut et envoie une requête AJAX au serveur d'application pour obtenir les informations de signature requises.
Après avoir reçu les informations de signature, le code crée un objet
FormDataavec les champs de formulaire requis.Il utilise ensuite la méthode
fetchpour envoyer une requête POST à l'URL OSS afin de télécharger le fichier.Dans un navigateur, accédez à votre serveur d'application. Cliquez sur Select File, choisissez un fichier et chargez-le.
Sur la page Buckets, ouvrez le compartiment que vous avez créé et vérifiez que l'objet chargé est bien présent.
Accédez à la page Instances dans la console ECS. Recherchez l'instance ECS cible par région et par ID d'instance, puis cliquez sur
dans la colonne Actions.Choisissez Release. Dans le menu qui s'affiche, cliquez sur Release.
Confirmez les détails de l'instance, sélectionnez Release Now, puis cliquez sur Next.
Passez en revue les ressources associées à libérer, prenez connaissance des risques liés aux données, puis cliquez sur Confirm.
Le disque système et toute adresse IP publique attribuée sont libérés avec l'instance.
Les groupes de sécurité, les vSwitches et les VPC ne sont pas libérés avec l'instance. Ces ressources sont gratuites, mais vous pouvez les supprimer si elles ne sont plus nécessaires.
Les EIP ne sont pas libérées avec l'instance et continuent d'engendrer des frais. Supprimez-les séparément si elles ne sont plus nécessaires.
Connectez-vous à la console OSS.
Cliquez sur Buckets, puis cliquez sur le nom du compartiment OSS cible.
Supprimez tous les objets présents dans le compartiment.
Dans le volet de navigation de gauche, cliquez sur Delete Bucket et suivez les instructions affichées à l'écran.
Connectez-vous à la console RAM en tant qu'utilisateur RAM disposant de privilèges d'administration.
Dans le volet de navigation de gauche, choisissez .
-
Sur la page Users, recherchez l'utilisateur RAM cible et cliquez sur Delete dans la colonne Actions.
Vous pouvez également sélectionner plusieurs utilisateurs RAM et cliquer sur Delete User sous la liste pour les déplacer tous vers la corbeille.
Dans la boîte de dialogue Delete User, examinez attentivement l'impact de la suppression, saisissez le nom de l'utilisateur RAM cible, puis cliquez sur Move to Recycle Bin.
Connectez-vous à la console RAM en tant qu'utilisateur RAM disposant de privilèges d'administration.
Dans le volet de navigation de gauche, choisissez .
Sur la page Roles, recherchez le rôle RAM cible et cliquez sur Delete Role dans la colonne Actions.
-
Dans la boîte de dialogue Delete Role, saisissez le nom du rôle RAM et cliquez sur Delete Role.
RemarqueSi des politiques sont attachées au rôle RAM, la suppression du rôle les détache également.
Étape 5 : Accorder des permissions au rôle RAM
Attachez la stratégie personnalisée que vous avez créée au rôle RAM. Cette opération confère au rôle les autorisations nécessaires lors de son endossement.
Signature côté serveur
Nous vous recommandons de configurer les informations sensibles, telles que AccessKey ID, AccessKey Secret et Role ARN, en tant que variables d'environnement. Cette pratique évite de les coder en dur dans votre code et réduit le risque de fuite d'identifiants.
Suivez les étapes ci-dessous pour définir les variables d'environnement.
Linux
macOS
Windows
Utilisez l'exemple de code suivant pour calculer une signature POST sur le serveur avec Signature Version 4 (recommandé). Pour plus d'informations sur la configuration du champ de formulaire policy, consultez la section champ de formulaire policy.
Java
Ajoutez les dépendances suivantes à votre projet Maven.
<!-- https://mvnrepository.com/artifact/com.aliyun/credentials-java -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.17.4</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>sts20150401</artifactId>
<version>1.1.6</version>
</dependency>
L'exemple de code suivant montre comment obtenir des identifiants d'accès temporaires et calculer une signature POST sur le serveur :
package com.aliyun.oss.web;
import com.aliyun.sts20150401.models.AssumeRoleResponse;
import com.aliyun.sts20150401.models.AssumeRoleResponseBody;
import com.aliyun.tea.TeaException;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.binary.Base64;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
@Controller
public class WebController {
// Basic OSS information. Replace with your actual bucket name, region ID, and host.
String bucket = "examplebucket";
String region = "cn-hangzhou";
String host = "http://examplebucket.oss-cn-hangzhou.aliyuncs.com";
// Set the upload callback URL, which is the address of your callback server. This must be a public URL. OSS uses this URL to send object upload information to your application server.
// The prefix (directory) for objects to be uploaded to OSS.
String upload_dir = "dir";
// The expiration time in seconds.
Long expire_time = 3600L;
/**
* Generates an expiration time based on a specified duration in seconds.
* @param seconds The duration in seconds.
* @return An ISO 8601 time string, such as "2014-12-01T12:00:00.000Z".
*/
public static String generateExpiration(long seconds) {
// Get the current timestamp in seconds.
long now = Instant.now().getEpochSecond();
// Calculate the expiration timestamp.
long expirationTime = now + seconds;
// Convert the timestamp to an Instant object and format it to ISO 8601.
Instant instant = Instant.ofEpochSecond(expirationTime);
// Define the time zone as UTC.
ZoneId zone = ZoneOffset.UTC;
// Convert the Instant to a ZonedDateTime.
ZonedDateTime zonedDateTime = instant.atZone(zone);
// Define the date-time format, for example, 2023-12-03T13:00:00.000Z.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
// Format the date and time.
String formattedDate = zonedDateTime.format(formatter);
// Return the result.
return formattedDate;
}
// Initialize the STS client.
public static com.aliyun.sts20150401.Client createStsClient() throws Exception {
// Hardcoding an AccessKey pair is a security risk and not recommended. This code is for reference only.
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 in your code's runtime environment.
.setAccessKeyId(System.getenv("OSS_ACCESS_KEY_ID"))
// Required. Make sure that the OSS_ACCESS_KEY_SECRET environment variable is set in your code's runtime environment.
.setAccessKeySecret(System.getenv("OSS_ACCESS_KEY_SECRET"));
// For more information about endpoints, see https://api.alibabacloud.com/product/Sts.
config.endpoint = "sts.cn-hangzhou.aliyuncs.com";
return new com.aliyun.sts20150401.Client(config);
}
/**
* Obtain an STS temporary credential.
* @return An AssumeRoleResponseBodyCredentials object.
*/
public static AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials getCredential() throws Exception {
com.aliyun.sts20150401.Client client = WebController.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 in your code's runtime environment.
.setRoleArn(System.getenv("OSS_STS_ROLE_ARN"))
.setRoleSessionName("yourRoleSessionName");// A custom session name.
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
try {
// If you copy this code to run, print the API return value.
AssumeRoleResponse response = client.assumeRoleWithOptions(assumeRoleRequest, runtime);
// The credentials object contains the AccessKeyId, AccessKeySecret, and SecurityToken.
return response.body.credentials;
} catch (TeaException error) {
// This is for demonstration only. Handle exceptions with caution and do not ignore them in your project.
// Error message
System.out.println(error.getMessage());
// Diagnostic address
System.out.println(error.getData().get("Recommend"));
com.aliyun.teautil.Common.assertAsString(error.message);
}
// Return a default error response object to avoid returning null.
AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials defaultCredentials = new AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials();
defaultCredentials.accessKeyId = "ERROR_ACCESS_KEY_ID";
defaultCredentials.accessKeySecret = "ERROR_ACCESS_KEY_SECRET";
defaultCredentials.securityToken = "ERROR_SECURITY_TOKEN";
return defaultCredentials;
}
@GetMapping("/get_post_signature_for_oss_upload")
public ResponseEntity<Map<String, String>> getPostSignatureForOssUpload() throws Exception {
AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials sts_data = getCredential();
String accesskeyid = sts_data.accessKeyId;
String accesskeysecret = sts_data.accessKeySecret;
String securitytoken = sts_data.securityToken;
// Get the date for x-oss-credential. This is the current date in yyyyMMdd format.
ZonedDateTime today = ZonedDateTime.now().withZoneSameInstant(java.time.ZoneOffset.UTC);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
String date = today.format(formatter);
// Get x-oss-date.
ZonedDateTime now = ZonedDateTime.now().withZoneSameInstant(java.time.ZoneOffset.UTC);
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'");
String x_oss_date = now.format(formatter2);
// Step 1: Create a policy.
String x_oss_credential = accesskeyid + "/" + date + "/" + region + "/oss/aliyun_v4_request";
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> policy = new HashMap<>();
policy.put("expiration", generateExpiration(expire_time));
List<Object> conditions = new ArrayList<>();
Map<String, String> bucketCondition = new HashMap<>();
bucketCondition.put("bucket", bucket);
conditions.add(bucketCondition);
Map<String, String> securityTokenCondition = new HashMap<>();
securityTokenCondition.put("x-oss-security-token", securitytoken);
conditions.add(securityTokenCondition);
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", x_oss_credential); // Replace with your actual AccessKey ID.
conditions.add(credentialCondition);
Map<String, String> dateCondition = new HashMap<>();
dateCondition.put("x-oss-date", x_oss_date);
conditions.add(dateCondition);
conditions.add(Arrays.asList("content-length-range", 1, 10240000));
conditions.add(Arrays.asList("eq", "$success_action_status", "200"));
conditions.add(Arrays.asList("starts-with", "$key", upload_dir));
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: " + stringToSign);
// Step 3: Calculate the signing key.
byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), date);
byte[] dateRegionKey = hmacsha256(dateKey, region);
byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss");
byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request");
// System.out.println("signingKey: " + BinaryUtil.toBase64String(signingKey));
// Step 4: Calculate the signature.
byte[] result = hmacsha256(signingKey, stringToSign);
String signature = BinaryUtil.toHex(result);
// System.out.println("signature:" + signature);
Map<String, String> response = new HashMap<>();
// Add the data to the map.
response.put("version", "OSS4-HMAC-SHA256");
response.put("policy", stringToSign);
response.put("x_oss_credential", x_oss_credential);
response.put("x_oss_date", x_oss_date);
response.put("signature", signature);
response.put("security_token", securitytoken);
response.put("dir", upload_dir);
response.put("host", host);
// Return a ResponseEntity with status code 200 (OK) to the web client for the PostObject operation.
return ResponseEntity.ok(response);
}
public static byte[] hmacsha256(byte[] key, String data) {
try {
// Initialize the HmacSHA256 key specification.
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
// Get an HmacSHA256 Mac instance.
Mac mac = Mac.getInstance("HmacSHA256");
// Initialize the Mac object with the key.
mac.init(secretKeySpec);
// Calculate the HMAC signature for the data.
byte[] hmacBytes = mac.doFinal(data.getBytes());
return hmacBytes;
} catch (Exception e) {
throw new RuntimeException("Failed to calculate HMAC-SHA256", e);
}
}
}
Python
Exécutez les commandes suivantes pour installer les dépendances.
pip install flask
pip install alibabacloud_tea_openapi alibabacloud_sts20150401 alibabacloud_credentials
L'exemple de code suivant montre comment obtenir un jeton d'accès temporaire (jeton STS), construire une politique de téléversement et calculer une signature POST sur le serveur.
from flask import Flask, render_template, jsonify
from alibabacloud_tea_openapi.models import Config
from alibabacloud_sts20150401.client import Client as Sts20150401Client
from alibabacloud_sts20150401 import models as sts_20150401_models
from alibabacloud_credentials.client import Client as CredentialClient
import os
import json
import base64
import hmac
import datetime
import time
import hashlib
app = Flask(__name__)
# Configure the OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, and OSS_STS_ROLE_ARN environment variables.
access_key_id = os.environ.get('OSS_ACCESS_KEY_ID')
access_key_secret = os.environ.get('OSS_ACCESS_KEY_SECRET')
role_arn_for_oss_upload = os.environ.get('OSS_STS_ROLE_ARN')
# A custom session name.
role_session_name = 'yourRoleSessionName'
# Replace with your actual bucket name, region ID, and host.
bucket = 'examplebucket'
region_id = 'cn-hangzhou'
host = 'http://examplebucket.oss-cn-hangzhou.aliyuncs.com'
# The expiration time in seconds.
expire_time = 3600
# The prefix (directory) for objects to be uploaded to OSS.
upload_dir = 'dir'
def hmacsha256(key, data):
"""
Calculates the HMAC-SHA256 hash value.
:param key: The key for calculating the hash, in bytes.
:param data: The data to be hashed, as a string.
:return: The calculated HMAC-SHA256 hash value, in bytes.
"""
try:
mac = hmac.new(key, data.encode(), hashlib.sha256)
hmacBytes = mac.digest()
return hmacBytes
except Exception as e:
raise RuntimeError(f"Failed to calculate HMAC-SHA256 due to {e}")
@app.route("/")
def hello_world():
return render_template('index.html')
@app.route('/get_post_signature_for_oss_upload', methods=['GET'])
def generate_upload_params():
# Initialize the configuration and pass the credentials directly.
config = Config(
region_id=region_id,
access_key_id=access_key_id,
access_key_secret=access_key_secret
)
# Create an STS client and obtain a temporary credential.
sts_client = Sts20150401Client(config=config)
assume_role_request = sts_20150401_models.AssumeRoleRequest(
role_arn=role_arn_for_oss_upload,
role_session_name=role_session_name
)
response = sts_client.assume_role(assume_role_request)
token_data = response.body.credentials.to_map()
# Use the temporary credential returned by STS.
temp_access_key_id = token_data['AccessKeyId']
temp_access_key_secret = token_data['AccessKeySecret']
security_token = token_data['SecurityToken']
now = int(time.time())
# Convert the timestamp to a datetime object.
dt_obj = datetime.datetime.utcfromtimestamp(now)
# Add 3 hours to the current time to set the request expiration time.
dt_obj_plus_3h = dt_obj + datetime.timedelta(hours=3)
# Request time.
dt_obj_1 = dt_obj.strftime('%Y%m%dT%H%M%S') + 'Z'
# Request date.
dt_obj_2 = dt_obj.strftime('%Y%m%d')
# Request expiration time.
expiration_time = dt_obj_plus_3h.strftime('%Y-%m-%dT%H:%M:%S.000Z')
# Construct the policy and generate the signature.
policy = {
"expiration": expiration_time,
"conditions": [
["eq", "$success_action_status", "200"],
{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
{"x-oss-credential": f"{temp_access_key_id}/{dt_obj_2}/cn-hangzhou/oss/aliyun_v4_request"},
{"x-oss-security-token": security_token},
{"x-oss-date": dt_obj_1},
]
}
print(dt_obj_1)
policy_str = json.dumps(policy).strip()
# Step 2: Construct the string to sign.
stringToSign = base64.b64encode(policy_str.encode()).decode()
# Step 3: Calculate the signing key.
dateKey = hmacsha256(("aliyun_v4" + temp_access_key_secret).encode(), dt_obj_2)
dateRegionKey = hmacsha256(dateKey, "cn-hangzhou")
dateRegionServiceKey = hmacsha256(dateRegionKey, "oss")
signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request")
# Step 4: Calculate the signature.
result = hmacsha256(signingKey, stringToSign)
signature = result.hex()
# Construct the response data.
response_data = {
'policy': stringToSign, # The policy form field.
'x_oss_signature_version': "OSS4-HMAC-SHA256", # The signature version and algorithm. This is fixed to OSS4-HMAC-SHA256.
'x_oss_credential': f"{temp_access_key_id}/{dt_obj_2}/cn-hangzhou/oss/aliyun_v4_request", # Specifies the credential scope.
'x_oss_date': dt_obj_1, # The request time.
'signature': signature, # The calculated signature.
'host': host,
'dir': upload_dir,
'security_token': security_token # The security token.
}
return jsonify(response_data)
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8000) # If you need to listen on other addresses such as 0.0.0.0, you must add a server-side authentication mechanism.
Node.js
Exécutez les commandes suivantes pour installer les dépendances.
npm install ali-oss
npm install @alicloud/credentials
npm install express
L'exemple de code suivant montre comment obtenir un jeton d'accès temporaire (jeton STS), construire une politique de téléversement et calculer une signature POST sur le serveur.
const express = require('express');
const OSS = require('ali-oss');
const { STS } = require('ali-oss');
const { getCredential } = require('ali-oss/lib/common/signUtils');
const { getStandardRegion } = require('ali-oss/lib/common/utils/getStandardRegion');
const { policy2Str } = require('ali-oss/lib/common/utils/policy2Str');
const app = express();
const PORT = process.env.PORT || 8000; // The port number for service requests.
// Set the static file directory.
app.use(express.static('templates'));
const GenerateSignature = async () => {
// Initialize the STS client.
let sts = new STS({
accessKeyId: process.env.OSS_ACCESS_KEY_ID, // Get the AccessKey ID of the RAM user from the environment variable.
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET // Get the AccessKey Secret of the RAM user from the environment variable.
});
// Call the assumeRole operation to obtain a temporary STS access credential.
const result = await sts.assumeRole(process.env.OSS_STS_ROLE_ARN, '', '3600', 'yourRoleSessionName'); // Get the RAM role ARN from the environment variable. The temporary access credential is valid for 3,600 seconds, and the role session name is a custom value, such as yourRoleSessionName.
// Extract the AccessKeyId, AccessKeySecret, and SecurityToken from the temporary access credential.
const accessKeyId = result.credentials.AccessKeyId;
const accessKeySecret = result.credentials.AccessKeySecret;
const securityToken = result.credentials.SecurityToken;
// Initialize the OSS client.
const client = new OSS({
bucket: 'examplebucket', // Replace with the name of the destination bucket.
region: 'cn-hangzhou', // Replace with the region of the destination bucket.
accessKeyId,
accessKeySecret,
stsToken: securityToken,
refreshSTSTokenInterval: 0,
refreshSTSToken: async () => {
const { accessKeyId, accessKeySecret, securityToken } = await client.getCredential();
return { accessKeyId, accessKeySecret, stsToken: securityToken };
},
});
// Create a form data map.
const formData = new Map();
// Set the signature expiration time to 10 minutes from the current time.
const date = new Date();
const expirationDate = new Date(date);
expirationDate.setMinutes(date.getMinutes() + 10);
// Format the date to a UTC time string that complies with ISO 8601.
function padTo2Digits(num) {
return num.toString().padStart(2, '0');
}
function formatDateToUTC(date) {
return (
date.getUTCFullYear() +
padTo2Digits(date.getUTCMonth() + 1) +
padTo2Digits(date.getUTCDate()) +
'T' +
padTo2Digits(date.getUTCHours()) +
padTo2Digits(date.getUTCMinutes()) +
padTo2Digits(date.getUTCSeconds()) +
'Z'
);
}
const formattedDate = formatDateToUTC(expirationDate);
// Generate x-oss-credential and set the form data.
const credential = getCredential(formattedDate.split('T')[0], getStandardRegion(client.options.region), client.options.accessKeyId);
formData.set('x_oss_date', formattedDate);
formData.set('x_oss_credential', credential);
formData.set('x_oss_signature_version', 'OSS4-HMAC-SHA256');
// Create the policy.
// This example policy lists only the required conditions.
const policy = {
expiration: expirationDate.toISOString(),
conditions: [
{ 'bucket': 'examplebucket'},
{ 'x-oss-credential': credential },
{ 'x-oss-signature-version': 'OSS4-HMAC-SHA256' },
{ 'x-oss-date': formattedDate },
],
};
// If an STS token exists, add it to the policy and form data.
if (client.options.stsToken) {
policy.conditions.push({ 'x-oss-security-token': client.options.stsToken });
formData.set('security_token', client.options.stsToken);
}
// Generate the signature and set the form data.
const signature = client.signPostObjectPolicyV4(policy, date);
formData.set('policy', Buffer.from(policy2Str(policy), 'utf8').toString('base64'));
formData.set('signature', signature);
// Return the form data.
return {
host: `http://${client.options.bucket}.oss-${client.options.region}.aliyuncs.com`,
policy: Buffer.from(policy2Str(policy), 'utf8').toString('base64'),
x_oss_signature_version: 'OSS4-HMAC-SHA256',
x_oss_credential: credential,
x_oss_date: formattedDate,
signature: signature,
dir: 'user-dir', // The prefix (directory) for the object to be uploaded to OSS.
security_token: client.options.stsToken
};
};
app.get('/get_post_signature_for_oss_upload', async (req, res) => {
try {
const result = await GenerateSignature();
res.json(result); // Return the generated signature data.
} catch (error) {
console.error('Error generating signature:', error);
res.status(500).send('Error generating signature');
}
});
app.listen(PORT, () => {
console.log(`Server is running on http://127.0.0.1:${PORT}`); // If you need to listen on other addresses such as 0.0.0.0, you must add a server-side authentication mechanism.
});
Go
Exécutez les commandes suivantes pour installer les dépendances.
go get -u github.com/aliyun/credentials-go
go mod tidy
L'exemple de code suivant montre comment obtenir des informations d'identification temporaires (jeton STS), construire une politique de téléchargement et calculer une signature POST sur le serveur.
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"hash"
"log"
"net/http"
"os"
"time"
"github.com/aliyun/credentials-go/credentials"
)
// Define global variables.
var (
region string
bucketName string
product = "oss"
)
// The PolicyToken struct stores the generated form data.
type PolicyToken struct {
Policy string `json:"policy"`
SecurityToken string `json:"security_token"`
SignatureVersion string `json:"x_oss_signature_version"`
Credential string `json:"x_oss_credential"`
Date string `json:"x_oss_date"`
Signature string `json:"signature"`
Host string `json:"host"`
Dir string `json:"dir"`
}
func main() {
// Define the default IP address and port string.
strIPPort := ":8000"
if len(os.Args) == 3 {
strIPPort = fmt.Sprintf("%s:%s", os.Args[1], os.Args[2])
} else if len(os.Args) != 1 {
fmt.Println("Usage : go run test1.go ")
fmt.Println("Usage : go run test1.go ip port ")
fmt.Println("")
os.Exit(0)
}
// Print the address and port on which the server is running.
fmt.Printf("server is running on %s \n", strIPPort)
// Register the function to handle root path requests.
http.HandleFunc("/", handlerRequest)
// Register the function to handle signature generation requests.
http.HandleFunc("/get_post_signature_for_oss_upload", handleGetPostSignature)
// Start the HTTP server.
err := http.ListenAndServe(strIPPort, nil)
if err != nil {
strError := fmt.Sprintf("http.ListenAndServe failed : %s \n", err.Error())
panic(strError)
}
}
// The handlerRequest function handles root path requests.
func handlerRequest(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
http.ServeFile(w, r, "templates/index.html")
return
}
http.NotFound(w, r)
}
// The handleGetPostSignature function handles signature generation requests.
func handleGetPostSignature(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
response := getPolicyToken()
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*") // Allow cross-origin requests.
w.Write([]byte(response))
return
}
http.NotFound(w, r)
}
// The getPolicyToken function generates the signature and credentials required for OSS uploads.
func getPolicyToken() string {
// Set the region of the bucket.
region = "cn-hangzhou"
// Replace with your bucket name.
bucketName = "examplebucket"
// Set the OSS upload address.
host := fmt.Sprintf("https://%s.oss-%s.aliyuncs.com", bucketName, region)
// Set the upload directory.
dir := "user-dir"
config := new(credentials.Config).
SetType("ram_role_arn").
SetAccessKeyId(os.Getenv("OSS_ACCESS_KEY_ID")).
SetAccessKeySecret(os.Getenv("OSS_ACCESS_KEY_SECRET")).
SetRoleArn("OSS_STS_ROLE_ARN").
SetRoleSessionName("Role_Session_Name").
SetPolicy("").
SetRoleSessionExpiration(3600)
// Create a credential provider based on the configuration.
provider, err := credentials.NewCredential(config)
if err != nil {
log.Fatalf("NewCredential fail, err:%v", err)
}
// Obtain credentials from the credential provider.
cred, err := provider.GetCredential()
if err != nil {
log.Fatalf("GetCredential fail, err:%v", err)
}
// Construct the policy.
utcTime := time.Now().UTC()
date := utcTime.Format("20060102")
expiration := utcTime.Add(1 * time.Hour)
policyMap := map[string]any{
"expiration": expiration.Format("2006-01-02T15:04:05.000Z"),
"conditions": []any{
map[string]string{"bucket": bucketName},
map[string]string{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
map[string]string{"x-oss-credential": fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request", *cred.AccessKeyId, date, region, product)},
map[string]string{"x-oss-date": utcTime.Format("20060102T150405Z")},
map[string]string{"x-oss-security-token": *cred.SecurityToken},
},
}
// Convert the policy to JSON format.
policy, err := json.Marshal(policyMap)
if err != nil {
log.Fatalf("json.Marshal fail, err:%v", err)
}
// Construct the string to sign.
stringToSign := base64.StdEncoding.EncodeToString([]byte(policy))
hmacHash := func() hash.Hash { return sha256.New() }
// Construct the signing key.
signingKey := "aliyun_v4" + *cred.AccessKeySecret
h1 := hmac.New(hmacHash, []byte(signingKey))
io.WriteString(h1, date)
h1Key := h1.Sum(nil)
h2 := hmac.New(hmacHash, h1Key)
io.WriteString(h2, region)
h2Key := h2.Sum(nil)
h3 := hmac.New(hmacHash, h2Key)
io.WriteString(h3, product)
h3Key := h3.Sum(nil)
h4 := hmac.New(hmacHash, h3Key)
io.WriteString(h4, "aliyun_v4_request")
h4Key := h4.Sum(nil)
// Generate the signature.
h := hmac.New(hmacHash, h4Key)
io.WriteString(h, stringToSign)
signature := hex.EncodeToString(h.Sum(nil))
// Construct the form to be returned to the client.
policyToken := PolicyToken{
Policy: stringToSign,
SecurityToken: *cred.SecurityToken,
SignatureVersion: "OSS4-HMAC-SHA256",
Credential: fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request", *cred.AccessKeyId, date, region, product),
Date: utcTime.UTC().Format("20060102T150405Z"),
Signature: signature,
Host: host, // The OSS upload address.
Dir: dir, // The upload directory.
}
response, err := json.Marshal(policyToken)
if err != nil {
fmt.Println("json err:", err)
}
return string(response)
}
PHP
Exécutez la commande suivante pour installer les dépendances.
composer install
L'exemple de code suivant montre comment obtenir des informations d'identification temporaires (jeton STS), construire une politique de téléchargement et calculer une signature POST sur le serveur.
<?php
// Import the Alibaba Cloud SDK.
require_once __DIR__ . '/vendor/autoload.php';
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use AlibabaCloud\Sts\Sts;
// Disable error display.
ini_set('display_errors', '0');
$bucket = 'examplebucket'; // Replace with your bucket name.
$region_id = 'cn-hangzhou'; // Replace with the region of your bucket.
$host = 'http://examplebucket.oss-cn-hangzhou.aliyuncs.com'; // Replace with your bucket's domain name.
$expire_time = 3600; // The expiration time in seconds.
$upload_dir = 'user-dir'; // The prefix (directory) for uploaded objects.
// Calculate HMAC-SHA256.
function hmacsha256($key, $data) {
return hash_hmac('sha256', $data, $key, true);
}
// Handle the request to get the POST signature.
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/get_post_signature_for_oss_upload') {
AlibabaCloud::accessKeyClient(getenv('OSS_ACCESS_KEY_ID'), getenv('OSS_ACCESS_KEY_SECRET'))
->regionId('cn-hangzhou')
->asDefaultClient();
// Create an STS request.
$request = Sts::v20150401()->assumeRole();
// Initiate the STS request and get the result.
// Set <YOUR_ROLE_SESSION_NAME> to a custom session name, such as oss-role-session.
// Replace <YOUR_ROLE_ARN> with the ARN of a RAM role that has permission to upload files to the specified OSS bucket.
$result = $request
->withRoleSessionName('oss-role-session')
->withDurationSeconds(3600)
->withRoleArn(getenv('OSS_STS_ROLE_ARN'))
->request();
// Get the credential information from the STS request result.
$tokenData = $result->get('Credentials');
// Construct the JSON data to return.
$tempAccessKeyId = $tokenData['AccessKeyId'];
$tempAccessKeySecret = $tokenData['AccessKeySecret'];
$securityToken = $tokenData['SecurityToken'];
$now = time();
$dtObj = gmdate('Ymd\THis\Z', $now);
$dtObj1 = gmdate('Ymd', $now);
$dtObjPlus3h = gmdate('Y-m-d\TH:i:s.u\Z', strtotime('+3 hours', $now));
// Construct the policy.
$policy = [
"expiration" => $dtObjPlus3h,
"conditions" => [
["x-oss-signature-version" => "OSS4-HMAC-SHA256"],
["x-oss-credential" => "{$tempAccessKeyId}/{$dtObj1}/cn-hangzhou/oss/aliyun_v4_request"],
["x-oss-security-token" => $securityToken],
["x-oss-date" => $dtObj],
]
];
$policyStr = json_encode($policy);
// Construct the string to sign.
$stringToSign = base64_encode($policyStr);
// Calculate the signing key.
$dateKey = hmacsha256(('aliyun_v4' . $tempAccessKeySecret), $dtObj1);
$dateRegionKey = hmacsha256($dateKey, 'cn-hangzhou');
$dateRegionServiceKey = hmacsha256($dateRegionKey, 'oss');
$signingKey = hmacsha256($dateRegionServiceKey, 'aliyun_v4_request');
// Calculate the signature.
$result = hmacsha256($signingKey, $stringToSign);
$signature = bin2hex($result);
// Return the signature data.
$responseData = [
'policy' => $stringToSign,
'x_oss_signature_version' => "OSS4-HMAC-SHA256",
'x_oss_credential' => "{$tempAccessKeyId}/{$dtObj1}/cn-hangzhou/oss/aliyun_v4_request",
'x_oss_date' => $dtObj,
'signature' => $signature,
'host' => $host,
'dir' => $upload_dir,
'security_token' => $securityToken
];
header('Content-Type: application/json');
echo json_encode($responseData);
exit;
}
// Home page route.
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/') {
echo file_get_contents(__DIR__ . '/public/index.html');
exit;
}
// Other routes.
http_response_code(404);
echo json_encode(['message' => 'Not Found']);
exit;
?>
Étape 3 : Configurer le client web
Téléchargement par formulaire côté client
Une fois que le client web a reçu les informations requises du serveur d'application, il construit une requête de formulaire HTML. Cette requête communique directement avec OSS pour télécharger le fichier.
Client web : Exemple de réponse
Le serveur d'application renvoie le jeton STS et la politique de téléchargement au client web.
{
"dir": "user-dirs",
"host": "http://examplebucket.oss-cn-hangzhou.aliyuncs.com",
"policy": "eyJl****",
"security_token": "CAIS****",
"signature": "9103****",
"x_oss_credential": "STS.NSpW****/20241127/cn-hangzhou/oss/aliyun_v4_request",
"x_oss_date": "20241127T060941Z",
"x_oss_signature_version": "OSS4-HMAC-SHA256"
}
Le tableau suivant décrit chaque champ du corps de la réponse.
|
Paramètre |
Description |
|
dir |
Spécifie le préfixe de nom d'objet requis pour les téléchargements. |
|
host |
Le nom de domaine du bucket de destination. |
|
policy |
La politique utilisée pour les téléchargements via un formulaire dans le navigateur. Pour plus d'informations, consultez Politique Post. |
|
security_token |
L'information d'identification temporaire utilisée pour l'authentification, fournie par STS. |
|
signature |
La signature générée à partir de la politique. Pour plus d'informations, consultez Signature Post. |
|
x_oss_credential |
Spécifie l'ensemble de paramètres utilisé pour dériver la clé de signature. |
|
x_oss_date |
L'heure de la requête au format ISO 8601, par exemple |
|
x_oss_signature_version |
La version de la signature et l'algorithme. La valeur est fixée à OSS4-HMAC-SHA256. |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Generate a signature on the server to upload a file to OSS</title>
</head>
<body>
<div class="container">
<form>
<div class="mb-3">
<label for="file" class="form-label">Select a file:</label>
<input type="file" class="form-control" id="file" name="file" required />
</div>
<button type="submit" class="btn btn-primary">Upload</button>
</form>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
const form = document.querySelector("form");
const fileInput = document.querySelector("#file");
form.addEventListener("submit", (event) => {
event.preventDefault();
const file = fileInput.files[0];
if (!file) {
alert('Please select a file to upload.');
return;
}
const filename = file.name;
fetch("/get_post_signature_for_oss_upload", { method: "GET" })
.then((response) => {
if (!response.ok) {
throw new Error("Failed to get signature");
}
return response.json();
})
.then((data) => {
let formData = new FormData();
formData.append("success_action_status", "200");
formData.append("policy", data.policy);
formData.append("x-oss-signature", data.signature);
formData.append("x-oss-signature-version", "OSS4-HMAC-SHA256");
formData.append("x-oss-credential", data.x_oss_credential);
formData.append("x-oss-date", data.x_oss_date);
formData.append("key", data.dir + file.name); // Object name
formData.append("x-oss-security-token", data.security_token);
formData.append("file", file); // file must be the last form field
return fetch(data.host, {
method: "POST",
body: formData
});
})
.then((response) => {
if (response.ok) {
console.log("Upload successful.");
alert("The file was uploaded successfully.");
} else {
console.log("Upload failed", response);
alert("Upload failed. Please try again later.");
}
})
.catch((error) => {
console.error("An error occurred:", error);
});
});
});
</script>
</body>
</html>
Si le téléchargement réussit, le message « Le fichier a été téléchargé avec succès. » s'affiche. En cas d'échec, un message d'erreur s'affiche.
Vérification
Après le déploiement, accédez à votre serveur d'application afin de tester la fonctionnalité de chargement direct avec des URL signées.
Configurations recommandées
Politique de chargement de fichiers
Vous pouvez modifier la section policy dans votre code pour définir les autorisations et les contraintes applicables aux chargements de fichiers vers OSS depuis un formulaire HTML. La politique au format JSON vous permet de restreindre les chargements en définissant des paramètres tels que le nom du compartiment autorisé, le préfixe d'objet, la date d'expiration, les méthodes HTTP autorisées, les limites de taille du contenu et les types de contenu.
{
"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/jpeg", "image/png"]],
["not-in", "$cache-control", ["no-cache"]]
]
}
Pour plus d'informations sur les paramètres de la politique, consultez la rubrique Post Policy.
Signature côté serveur et rappel de chargement
Pour recevoir les métadonnées des fichiers chargés, telles que le nom et la taille du fichier, configurez un rappel de chargement. Une fois le fichier chargé, OSS envoie les informations relatives au fichier à votre serveur d'application. Pour en savoir plus, consultez la rubrique Server-side signing and direct upload with an upload callback.
Restreindre les origines CORS
Par souci de simplicité, l'origine autorisée a été précédemment définie sur le caractère générique *. Conformément aux bonnes pratiques de sécurité, vous devez remplacer ce caractère générique par l'URL spécifique de votre serveur d'application. Cela garantit que seules les requêtes cross-origin provenant de votre serveur sont autorisées.
|
Parameter |
Sample value |
|
Origin |
|
|
Allowed Methods |
POST, PUT, GET |
|
Allowed Headers |
* |
Nettoyage des ressources
Dans cette solution, vous avez créé une instance ECS, un compartiment OSS, un utilisateur RAM et un rôle RAM. Une fois les tests terminés, nettoyez ces ressources afin d'éviter des frais continus ou des risques de sécurité.
Libérer l'instance ECS
Si vous n'avez plus besoin de l'instance, libérez-la. Après la libération de l'instance, la facturation s'arrête et vous ne pouvez pas récupérer ses données.
Supprimer le compartiment OSS
Supprimer l'utilisateur RAM
Supprimer le rôle RAM
FAQ
Chargement multipart et reprise après interruption
Cette solution utilise le chargement par formulaire et ne prend pas en charge les chargements multipart ni la reprise après interruption. Pour utiliser ces méthodes, consultez les rubriques Resumable upload et Multipart upload.
Empêcher l'écrasement de fichiers
Définissez le paramètre x-oss-forbid-overwrite sur true dans les champs du formulaire de chargement. Par exemple :
formData.append('x-oss-forbid-overwrite', 'true');