Tous les produits
Search
Centre de documentation

IoT Platform:Mécanisme de signature

Dernière mise à jour :Aug 20, 2026

IoT Platform authentifie l'expéditeur de chaque requête API. Vous devez donc inclure une signature dans toutes les requêtes API utilisant le protocole HTTP ou HTTPS.

Méthode de signature

Pour signer une requête, accédez à la page AccessKey Management de la console afin d'obtenir l'AccessKey ID et l'AccessKey Secret de votre compte Alibaba Cloud. Générez ensuite un code d'authentification de message (MAC). L'AccessKey ID identifie l'utilisateur. L'AccessKey Secret est la clé servant à chiffrer la chaîne de signature et permettant au serveur de la vérifier. Gardez votre AccessKey Secret confidentiel.

Remarque

IoT Platform propose des kits de développement logiciel (SDK) côté serveur pour des langages tels que Java, Python et PHP. L'utilisation de ces SDK vous dispense de signer manuellement les requêtes. Pour savoir comment utiliser chaque SDK, consultez les rubriques Server-side SDKs (original) et Server-side SDKs (upgraded).

Pour signer la requête, suivez les étapes ci-dessous :

  1. Construisez une chaîne de requête canonique à partir des paramètres de la requête.

    1. Triez les paramètres.

      Classez les paramètres de requête par ordre alphabétique selon leur nom. Ces paramètres incluent les common request parameters ainsi que les paramètres personnalisés de l'API. N'incluez pas le paramètre Signature lui-même.

      Remarque

      Lorsque vous utilisez la méthode GET pour soumettre une requête, ces paramètres correspondent à la partie de l'URL de requête qui suit le ? et sont séparés par le caractère &.

    2. Encodez en URL le nom et la valeur de chaque paramètre de requête.

      Encodez les noms et les valeurs des paramètres en utilisant le jeu de caractères UTF-8 conformément aux règles définies dans la norme RFC 3986. Les règles d'encodage sont les suivantes :

      • Les caractères A à Z, a à z, 0 à 9, ainsi que les caractères -, _, . et ~ ne sont pas encodés.

      • Les autres caractères sont encodés au format %XY, où XY représente la valeur hexadécimale du code ASCII du caractère. Par exemple, un guillemet double (") est encodé sous la forme %22.

      • Les caractères UTF-8 étendus sont encodés au format %XY%ZA….

      • Un espace doit être encodé sous la forme %20 et non sous la forme d'un signe plus (+).

      Cette méthode d'encodage est similaire, mais non identique, à l'algorithme d'encodage du type MIME application/x-www-form-urlencoded.

      Si vous utilisez java.net.URLEncoder de la bibliothèque standard Java, encodez d'abord la chaîne à l'aide de la méthode percentEncode. Ensuite, dans la chaîne encodée, remplacez le signe plus (+) par %20, l'astérisque (*) par %2A, et %7E par un tilde (~). Vous obtenez ainsi une chaîne encodée conforme aux règles précédentes.

      private static final String ENCODING = "UTF-8";
      private static String percentEncode(String value) throws UnsupportedEncodingException {
      return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null;
      }
    3. Reliez le nom du paramètre encodé et sa valeur à l'aide d'un signe égal (=).

    4. Triez les paires paramètre-valeur par ordre alphabétique selon le nom du paramètre, puis concaténez-les en utilisant le symbole &.

    Une fois ces étapes terminées, vous obtenez la chaîne de requête canonique.

  2. Construisez la chaîne à signer.

    Créez la chaîne à signer en traitant la chaîne de requête canonique de l'étape 1 avec percentEncode. La chaîne doit respecter le format suivant :

    StringToSign=
      HTTPMethod + "&" +                      
      percentEncode("/") + "&" +              
      percentEncode(CanonicalizedQueryString)

    Description des paramètres :

    • HTTPMethod : la méthode HTTP utilisée pour envoyer la requête, telle que GET.

    • percentEncode("/") : la valeur encodée en UTF-8 de la barre oblique (/), soit « %2F ».

    • percentEncode(CanonicalizedQueryString) : la chaîne de requête canonique encodée en pourcentage.

  3. Calculez la valeur HMAC.

    Utilisez la chaîne StringToSign créée à l'étape 2 pour calculer la valeur HMAC telle que définie dans la norme RFC 2104.

    HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) )
    Important

    La clé utilisée pour le calcul de la signature est votre AccessKeySecret suivi d'un caractère esperluette (&) (code ASCII 38). L'algorithme de hachage est SHA1.

  4. Calculez la valeur de signature.

    Encodez la valeur HMAC de l'étape 3 en une chaîne à l'aide des règles d'encodage Base64. La chaîne résultante constitue la valeur de signature (Signature).

    Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
  5. Ajoutez la signature.

    Ajoutez le paramètre Signature aux paramètres de la requête. La valeur de ce paramètre est la signature résultante, qui doit être encodée en URL conformément à la norme RFC 3986.

Exemple de signature

Cet exemple illustre l'appel de l'API Pub. Supposons les valeurs de paramètres suivantes : AccessKeyId=testid, AccessKeySecret=testsecret, ProductKey=12345abcde, TopicFullName=/12345abcde/testdevice/user/get, MessageContent=aGVsbG8gd29ybGQ et Qos=0.

  1. Construisez l'URL de requête avant la signature.

    http://iot.cn-shanghai.aliyuncs.com/?Action=Pub&MessageContent=aGVsbG8gd29ybGQ&Timestamp=2018-07-31T07:43:57Z&SignatureVersion=1.0&Format=XML&Qos=0&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2018-01-20&AccessKeyId=testid&SignatureMethod=HMAC-SHA1&RegionId=cn-shanghai&ProductKey=12345abcde&TopicFullName=/12345abcde/testdevice/user/get
  2. Calculez la chaîne à signer, StringToSign.

    GET&%2F&AccessKeyId%3Dtestid%26Action%3DPub%26Format%3DXML%26MessageContent%3DaGVsbG8gd29ybGQ%26ProductKey%3D12345abcde%26Qos%3D0%26RegionId%3Dcn-shanghai%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf%26SignatureVersion%3D1.0%26Timestamp%3D2018-07-31T07%253A43%253A57Z%26TopicFullName%3D%252F12345abcde%252Ftestdevice%252Fuser%252Fget%26Version%3D2018-01-20
  3. Calculez la valeur de signature.

    Étant donné que l'AccessKeySecret est testsecret, la clé utilisée pour le calcul est testsecret&. La valeur de signature calculée est :

    NUh3otvAoXOZmG/a2gDShh6Ze9w=
  4. Ajoutez la signature à l'URL de requête en tant que paramètre Signature. L'URL finale est :

    http://iot.cn-shanghai.aliyuncs.com/?MessageContent=aGVsbG8gd29ybGQ&Action=Pub&Timestamp=2018-07-31T07%253A43%253A57Z&SignatureVersion=1.0&Format=XML&Qos=0&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2018-01-20&AccessKeyId=testid&Signature=NUh3otvAoXOZmG%2Fa2gDShh6Ze9w%3D&SignatureMethod=HMAC-SHA1&RegionId=cn-shanghai&ProductKey=12345abcde&TopicFullName=%2F12345abcde%2Ftestdevice%2Fuser%2Fget

Exemple de code Java

Le code Java suivant fournit un exemple de création d'une signature.

  1. Ajoutez les dépendances du projet Maven.

    <!-- Apache Commons Lang 3.x -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.12.0</version> <!-- Use the latest version -->
    </dependency>
    
    <!-- Apache Commons Codec -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.15</version> <!-- Use the latest version -->
    </dependency>
  2. Le fichier de configuration est Config.java.

    /*   
     * Copyright  2018 Alibaba. All rights reserved.
     */
    package com.aliyun.iot.demo.sign;
    
    /**
     * Configuration file for server-side API signing
     * 
     * @author: ali
     * @version: 0.1 2018-08-08 08:23:54
     */
    public class Config {
    
        // AccessKey information
        public static String accessKey = "123456******3456";
        public static String accessKeySecret = "123456******34567******4567890";
    
        public final static String CHARSET_UTF8 = "utf8";
    }

    Paramètre

    Exemple

    Description

    accessKey

    1234563456

    Connectez-vous à la console IoT Platform. Placez le pointeur sur votre photo de profil et cliquez sur AccessKey Management pour obtenir l'AccessKey ID et l'AccessKey Secret.

    Remarque

    Si vous utilisez un utilisateur Resource Access Management (RAM), vous devez accorder à cet utilisateur les autorisations de gestion d'IoT Platform (AliyunIOTFullAccess). Sinon, la connexion échouera. Pour savoir comment accorder des autorisations, consultez la rubrique Accorder à un utilisateur RAM des autorisations d'accès à IoT Platform.

    accessKeySecret

    123456345674567890

  3. Le fichier de configuration est UrlUtil.java.

    /*   
     * Copyright  2018 Alibaba. All rights reserved.
     */
    package com.aliyun.iot.demo.sign;
    
    import java.net.URLEncoder;
    import java.util.Map;
    
    import org.apache.commons.lang3.StringUtils;
    
    /**
     * URL processing class
     * 
     * @author: ali
     * @version: 0.1 2018-06-21 20:40:52
     */
    public class UrlUtil {
    
        private final static String CHARSET_UTF8 = "utf8";
    
        public static String urlEncode(String url) {
            if (!StringUtils.isEmpty(url)) {
                try {
                    url = URLEncoder.encode(url, "UTF-8");
                } catch (Exception e) {
                    System.out.println("URL encode error:" + e.getMessage());
                }
            }
            return url;
        }
    
        public static String generateQueryString(Map<String, String> params, boolean isEncodeKV) {
            StringBuilder canonicalizedQueryString = new StringBuilder();
            for (Map.Entry<String, String> entry : params.entrySet()) {
                if (isEncodeKV)
                    canonicalizedQueryString.append(percentEncode(entry.getKey())).append("=")
                            .append(percentEncode(entry.getValue())).append("&");
                else
                    canonicalizedQueryString.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            if (canonicalizedQueryString.length() > 1) {
                canonicalizedQueryString.setLength(canonicalizedQueryString.length() - 1);
            }
            return canonicalizedQueryString.toString();
        }
    
        public static String percentEncode(String value) {
            try {
                // After encoding with URLEncoder.encode, replace "+", "*", and "%7E" to meet the API encoding specifications.
                return value == null ? null
                        : URLEncoder.encode(value, CHARSET_UTF8).replace("+", "%20").replace("*", "%2A").replace("%7E",
                                "~");
            } catch (Exception e) {
    
            }
            return "";
        }
    }
  4. Le fichier de configuration est SignatureUtils.java.

    /*   
     * Copyright  2018 Alibaba. All rights reserved.
     */
    package com.aliyun.iot.demo.sign;
    
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.net.URLDecoder;
    import java.net.URLEncoder;
    import java.util.Map;
    import java.util.TreeMap;
    
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    
    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.lang3.StringUtils;
    
    /**
     * Server-side API signing
     * 
     * @author: ali
     * @version: 0.1 2018-06-21 20:47:05
     */
    public class SignatureUtils {
    
        private final static String CHARSET_UTF8 = "utf8";
        private final static String ALGORITHM = "HmacSHA1";
        private final static String SEPARATOR = "&";
    
        public static Map<String, String> splitQueryString(String url)
                throws URISyntaxException, UnsupportedEncodingException {
            URI uri = new URI(url);
            String query = uri.getQuery();
            final String[] pairs = query.split("&");
            TreeMap<String, String> queryMap = new TreeMap<String, String>();
            for (String pair : pairs) {
                final int idx = pair.indexOf("=");
                final String key = idx > 0 ? pair.substring(0, idx) : pair;
                if (!queryMap.containsKey(key)) {
                    queryMap.put(key, URLDecoder.decode(pair.substring(idx + 1), CHARSET_UTF8));
                }
            }
            return queryMap;
        }
    
        public static String generate(String method, Map<String, String> parameter, String accessKeySecret)
                throws Exception {
            String signString = generateSignString(method, parameter);
            System.out.println("signString---" + signString);
            byte[] signBytes = hmacSHA1Signature(accessKeySecret + "&", signString);
            String signature = newStringByBase64(signBytes);
            System.out.println("signature----" + signature);
            if ("POST".equals(method))
                return signature;
            return URLEncoder.encode(signature, "UTF-8");
        }
    
        public static String generateSignString(String httpMethod, Map<String, String> parameter) throws IOException {
            TreeMap<String, String> sortParameter = new TreeMap<String, String>();
            sortParameter.putAll(parameter);
            String canonicalizedQueryString = UrlUtil.generateQueryString(sortParameter, true);
            if (null == httpMethod) {
                throw new RuntimeException("httpMethod can not be empty");
            }
            StringBuilder stringToSign = new StringBuilder();
            stringToSign.append(httpMethod).append(SEPARATOR);
            stringToSign.append(percentEncode("/")).append(SEPARATOR);
            stringToSign.append(percentEncode(canonicalizedQueryString));
            return stringToSign.toString();
        }
    
        public static String percentEncode(String value) {
            try {
                return value == null ? null
                        : URLEncoder.encode(value, CHARSET_UTF8).replace("+", "%20").replace("*", "%2A").replace("%7E",
                                "~");
            } catch (Exception e) {
            }
            return "";
        }
    
        public static byte[] hmacSHA1Signature(String secret, String baseString) throws Exception {
            if (StringUtils.isEmpty(secret)) {
                throw new IOException("secret can not be empty");
            }
            if (StringUtils.isEmpty(baseString)) {
                return null;
            }
            Mac mac = Mac.getInstance("HmacSHA1");
            SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(CHARSET_UTF8), ALGORITHM);
            mac.init(keySpec);
            return mac.doFinal(baseString.getBytes(CHARSET_UTF8));
        }
    
        public static String newStringByBase64(byte[] bytes) throws UnsupportedEncodingException {
            if (bytes == null || bytes.length == 0) {
                return null;
            }
            return new String(Base64.encodeBase64(bytes, false), CHARSET_UTF8);
        }
    }
  5. Créez le fichier principal Main.java.

    /*   
     * Copyright  2018 Alibaba. All rights reserved.
     */
    package com.aliyun.iot.demo.sign;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Main entry for the signing tool
     * 
     * @author: ali
     * @version: 0.1 2018-09-18 15:06:48
     */
    public class Main {
    
        // 1. Modify the AccessKey information in Config.java.
        // 2. Method 2 is recommended. All parameters must be specified.
        // 3. "Final signature" is the final signature result.
        public static void main(String[] args) throws UnsupportedEncodingException {
    
            // Method 1
            System.out.println("Method 1:");
            String str = "GET&%2F&AccessKeyId%3D" + Config.accessKey
                    + "%26Action%3DRegisterDevice%26DeviceName%3D1533023037%26Format%3DJSON%26ProductKey%3DaxxxUtgaRLB%26RegionId%3Dcn-shanghai%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D1533023037%26SignatureVersion%3D1.0%26Timestamp%3D2018-07-31T07%253A43%253A57Z%26Version%3D2018-01-20";
            byte[] signBytes;
            try {
                signBytes = SignatureUtils.hmacSHA1Signature(Config.accessKeySecret + "&", str.toString());
                String signature = SignatureUtils.newStringByBase64(signBytes);
                System.out.println("signString---" + str);
                System.out.println("signature----" + signature);
                System.out.println("Final signature: " + URLEncoder.encode(signature, Config.CHARSET_UTF8));
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println();
    
            // Method 2
            System.out.println("Method 2:");
            Map<String, String> map = new HashMap<String, String>();
            // Common parameters
            map.put("Format", "JSON");
            map.put("Version", "2018-01-20");
            map.put("AccessKeyId", Config.accessKey);
            map.put("SignatureMethod", "HMAC-SHA1");
            map.put("Timestamp", "2018-07-31T07:43:57Z");
            map.put("SignatureVersion", "1.0");
            map.put("SignatureNonce", "1533023037");
            map.put("RegionId", "cn-shanghai");
            // Request parameters
            map.put("Action", "RegisterDevice");
            map.put("DeviceName", "1533023037");
            map.put("ProductKey", "axxxUtgaRLB");
            try {
                String signature = SignatureUtils.generate("GET", map, Config.accessKeySecret);
                System.out.println("Final signature: " + signature);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println();
        }
    }