Todos os produtos
Search
Central de documentação

IoT Platform:Mecanismo de assinatura

Última atualização: Aug 20, 2026

O IoT Platform autentica o remetente de cada solicitação de API. Por isso, inclua uma assinatura em todas as solicitações de API que utilizam os protocolos HTTP ou HTTPS.

Método de assinatura

Para assinar uma solicitação, acesse a página AccessKey Management no console e obtenha o AccessKey ID e o AccessKey secret da sua conta Alibaba Cloud. Em seguida, gere um Código de Autenticação de Mensagem (MAC). O AccessKey ID identifica o usuário. O AccessKey secret é a chave usada para criptografar a string de assinatura e permitir que o servidor a verifique. Mantenha seu AccessKey secret em sigilo absoluto.

Nota

O IoT Platform oferece kits de desenvolvimento de software (SDKs) para o lado do servidor em linguagens como Java, Python e PHP. O uso desses SDKs elimina a necessidade de assinar manualmente. Para obter instruções sobre como utilizar cada SDK, consulte Server-side SDKs (original) e Server-side SDKs (upgraded).

Siga as etapas abaixo para assinar a solicitação:

  1. Construa uma string de consulta canônica a partir dos parâmetros da solicitação.

    1. Ordene os parâmetros.

      Organize os parâmetros da solicitação em ordem alfabética pelo nome do parâmetro. Esses parâmetros incluem common request parameters e os parâmetros personalizados da API. Não inclua o próprio parâmetro Signature.

      Nota

      Ao usar o método GET para enviar uma solicitação, esses parâmetros correspondem à parte da URL da solicitação que segue o caractere ? e são separados por &.

    2. Codifique o nome e o valor de cada parâmetro da solicitação na URL.

      Codifique os nomes e valores dos parâmetros usando o conjunto de caracteres UTF-8 conforme as regras definidas na RFC 3986. As regras de codificação são:

      • Os caracteres A a Z, a a z, 0 a 9, além dos caracteres -, _, . e ~ não são codificados.

      • Demais caracteres são codificados no formato %XY, onde XY representa o valor hexadecimal do código ASCII do caractere. Por exemplo, aspas duplas (") são codificadas como %22.

      • Caracteres UTF-8 estendidos seguem o formato %XY%ZA….

      • O espaço deve ser codificado como %20, e não como sinal de adição (+).

      Esse método de codificação é semelhante, mas não idêntico, ao algoritmo de codificação do tipo MIME (Multipurpose Internet Mail Extensions) application/x-www-form-urlencoded.

      Caso utilize java.net.URLEncoder da biblioteca padrão Java, codifique primeiro a string com o método percentEncode. Depois, na string codificada, substitua o sinal de adição (+) por %20, o asterisco (*) por %2A e %7E por til (~). Isso gera uma string codificada em conformidade com as regras anteriores.

      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. Conecte o nome do parâmetro codificado e seu respectivo valor com um sinal de igual (=).

    4. Ordene os pares parâmetro-valor alfabeticamente pelo nome do parâmetro e concatene-os usando o símbolo &.

    Após concluir essas etapas, você obtém a string de consulta canônica.

  2. Construa a string a ser assinada.

    Crie a string de assinatura processando a string de consulta canônica da Etapa 1 com percentEncode. A string deve seguir o formato abaixo:

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

    Descrição dos parâmetros:

    • HTTPMethod: método HTTP utilizado para enviar a solicitação, como GET.

    • percentEncode("/"): valor codificado em UTF-8 da barra (/), que corresponde a "%2F".

    • percentEncode(CanonicalizedQueryString): string de consulta canônica com codificação percentual.

  3. Calcule o valor HMAC.

    Utilize a string StringToSign criada na Etapa 2 para calcular o valor HMAC conforme definido na RFC 2104.

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

    A chave para o cálculo da assinatura é o seu AccessKeySecret seguido pelo caractere "e" comercial (&) (código ASCII 38). O algoritmo de hash é SHA1.

  4. Calcule o valor da assinatura.

    Codifique o valor HMAC da Etapa 3 em uma string usando as regras de codificação Base64. A string resultante é o valor da assinatura (Signature).

    Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
  5. Adicione a assinatura.

    Inclua o parâmetro Signature nos parâmetros da solicitação. O valor desse parâmetro é a assinatura resultante, que deve ser codificada na URL conforme especificado na RFC 3986.

Exemplo de assinatura

Este exemplo demonstra como chamar a API Pub. Considere os seguintes valores de parâmetros para este cenário: AccessKeyId=testid, AccessKeySecret=testsecret, ProductKey=12345abcde, TopicFullName=/12345abcde/testdevice/user/get, MessageContent=aGVsbG8gd29ybGQ e Qos=0.

  1. Construa a URL da solicitação antes da assinatura.

    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. Calcule a string a ser assinada, 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. Calcule o valor da assinatura.

    Como o AccessKeySecret é testsecret, a chave utilizada para o cálculo é testsecret&. O valor da assinatura calculada é:

    NUh3otvAoXOZmG/a2gDShh6Ze9w=
  4. Adicione a assinatura à URL da solicitação como o parâmetro Signature. A URL final é:

    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

Exemplo de código Java

O código Java a seguir apresenta um exemplo de criação de assinatura.

  1. Adicione as dependências do projeto 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. O arquivo de configuração é 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";
    }

    Parâmetro

    Exemplo

    Descrição

    accessKey

    1234563456

    Faça login no console do IoT Platform. Passe o ponteiro do mouse sobre sua foto de perfil e clique em AccessKey Management para obter o AccessKey ID e o AccessKey secret.

    Nota

    Se você utilizar um usuário do Resource Access Management (RAM), será necessário conceder a esse usuário permissões para gerenciar o IoT Platform (AliyunIOTFullAccess). Caso contrário, a conexão falhará. Para obter informações sobre como conceder permissões, consulte Grant a RAM user permissions to access IoT Platform.

    accessKeySecret

    123456345674567890

  3. O arquivo de configuração é 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. O arquivo de configuração é 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. Crie o arquivo de entrada 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();
        }
    }