Tous les produits
Search
Centre de documentation

Object Storage Service:Server-side signing for direct upload

Dernière mise à jour :Sep 01, 2026

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

image

Pour mettre en œuvre le chargement direct avec signature côté serveur, suivez ces trois étapes :

Remarque

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.

  1. 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.

  2. 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.

  3. Configurez le client web : Construisez une requête de formulaire HTML et utilisez la signature pour charger le fichier vers OSS.

Exemples de projets

É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.

  1. Connectez-vous à la console OSS.

  2. Dans le volet de navigation de gauche, cliquez sur Buckets, puis cliquez sur Create Bucket.

  3. 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)

  4. Cliquez sur Create.

Configurer une règle CORS

Configurez une règle CORS pour votre bucket OSS.

  1. Sur la page Buckets, cliquez sur le bucket cible.

  2. Sur la page CORS, cliquez sur Create Rule.

  3. Dans le panneau Create Rule, définissez les paramètres suivants.

    Paramètre

    Valeur d’exemple

    Origin

    *

    Allowed Methods

    POST, PUT, GET

    Allowed Headers

    *

  1. Cliquez sur OK.

Étape 2 : Configurer le serveur

Remarque

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.

  1. Sélectionner une région et une méthode de facturation

    1. Choisissez une méthode de facturation adaptée à vos besoins métier. Ce tutoriel utilise le mode pay-as-you-go pour sa flexibilité.

    2. 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.

  1. 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.

    Remarque

    Vous 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.

  1. 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 publique Alibaba Cloud Linux 3.2104 LTS 64-bit.

  1. 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.

  1. 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.

    Remarque
    • Si 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.

  1. 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).

    Remarque
    • Les 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.

  1. Créer une paire de clés

    1. 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.

    2. L’utilisateur root dispose des privilèges les plus élevés dans le système d’exploitation, et l’utilisation de root comme nom de connexion peut présenter des risques de sécurité. Nous vous recommandons d’utiliser ecs-user comme nom de connexion.

      Remarque

      Aprè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.

  1. 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

  1. 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.

  2. Dans la boîte de dialogue Remote connection, cliquez sur Sign in now à côté de Workbench.

  3. 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.

  4. 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.

  5. 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

Remarque

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.

  1. Connectez-vous à la console RAM avec votre compte Alibaba Cloud ou en tant qu’administrateur RAM.

  2. Dans le volet de navigation de gauche, choisissez Identities > Users.

  3. Cliquez sur Create User.

  4. Saisissez un Logon Name et un Display Name.

  5. Dans la section Access Mode, sélectionnez Programmatic access, puis cliquez sur OK.

Important

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é.

  1. 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.

  1. Dans le volet de navigation de gauche, choisissez Identities > Users.

  2. Sur la page Users, recherchez l’utilisateur RAM cible, puis cliquez sur Add Permissions dans la colonne Actions.

  3. Sur la page Grant Permission, sélectionnez la stratégie système AliyunSTSAssumeRoleAccess.

    Remarque

    La 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.

  4. 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.

  1. Dans le volet de navigation de gauche, choisissez Identities > Roles.

  2. Cliquez sur Create Role. Pour Principal Type, sélectionnez Alibaba Cloud Account.

  3. Sélectionnez le compte Alibaba Cloud actuel et cliquez sur OK.

  4. Saisissez un nom de rôle et cliquez sur OK.

  5. 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.

  1. Dans le volet de navigation de gauche, choisissez Permissions > Policies.

  2. Cliquez sur Create Policy.

  3. Sur la page Create Policy, cliquez sur JSON Editor et remplacez <Bucket name> dans le script par le nom du bucket web-direct-upload que vous avez créé dans la section Preparations.

    {
      "Version": "1",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": "oss:PutObject",
          "Resource": "acs:oss:*:*:<BucketName>/*"
        }
      ]
    }
  4. Après avoir configuré la politique, cliquez sur OK.

  5. Dans la boîte de dialogue Create Policy, saisissez un Policy Name et cliquez sur OK.

  6. É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.

    1. Dans le volet de navigation de gauche, sélectionnez Identities > Roles.

    2. Sur la page Roles, localisez le rôle RAM cible, puis cliquez sur Add Permissions dans la colonne Actions.

    3. Sur la page Grant Permission, sélectionnez Custom Policy, puis choisissez la stratégie que vous avez créée.

    4. Cliquez sur OK.

    Signature côté serveur

    Remarque

    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

    1. 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
    2. Exécutez la commande suivante pour appliquer les modifications.

      source  ~/.bashrc
    3. 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

    macOS

    1. Dans le terminal, exécutez la commande suivante pour vérifier votre shell par défaut.

      echo $SHELL
    2. Suivez les instructions correspondant à votre shell par défaut.

      Zsh

      1. 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
      2. Exécutez la commande suivante pour appliquer les modifications.

        source ~/.zshrc
      3. 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

      1. 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
      2. Exécutez la commande suivante pour appliquer les modifications.

        source ~/.bash_profile
      3. 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

    Windows

    1. 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"
    2. Ouvrez une nouvelle fenêtre CMD.

    3. 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%

    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 20231203T121212Z.

    x_oss_signature_version

    La version de la signature et l'algorithme. La valeur est fixée à OSS4-HMAC-SHA256.

    • 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.

    Remarque
    • À 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.

    <!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>
    • 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 FormData avec les champs de formulaire requis.

    • Il utilise ensuite la méthode fetch pour envoyer une requête POST à l'URL OSS afin de télécharger le fichier.

    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.

    1. Dans un navigateur, accédez à votre serveur d'application. Cliquez sur Select File, choisissez un fichier et chargez-le.

    2. Sur la page Buckets, ouvrez le compartiment que vous avez créé et vérifiez que l'objet chargé est bien présent.

    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

    http://<your_application_server_address>

    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.

    1. 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 image dans la colonne Actions.

    2. Choisissez Release. Dans le menu qui s'affiche, cliquez sur Release.

    3. Confirmez les détails de l'instance, sélectionnez Release Now, puis cliquez sur Next.

    4. Passez en revue les ressources associées à libérer, prenez connaissance des risques liés aux données, puis cliquez sur Confirm.

    Remarque
    • 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.

    Supprimer le compartiment OSS

    1. Connectez-vous à la console OSS.

    2. Cliquez sur Buckets, puis cliquez sur le nom du compartiment OSS cible.

    3. Supprimez tous les objets présents dans le compartiment.

    4. Dans le volet de navigation de gauche, cliquez sur Delete Bucket et suivez les instructions affichées à l'écran.

    Supprimer l'utilisateur RAM

    1. Connectez-vous à la console RAM en tant qu'utilisateur RAM disposant de privilèges d'administration.

    2. Dans le volet de navigation de gauche, choisissez .

    3. 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.

    4. 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.

    Supprimer le rôle RAM

    1. Connectez-vous à la console RAM en tant qu'utilisateur RAM disposant de privilèges d'administration.

    2. Dans le volet de navigation de gauche, choisissez .

    3. Sur la page Roles, recherchez le rôle RAM cible et cliquez sur Delete Role dans la colonne Actions.

    4. Dans la boîte de dialogue Delete Role, saisissez le nom du rôle RAM et cliquez sur Delete Role.

      Remarque

      Si des politiques sont attachées au rôle RAM, la suppression du rôle les détache également.

    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');