Observação: o Plano Premium da Plataforma Google Maps não está mais disponível para inscrições ou novos clientes.
Assinaturas digitais
Como funcionam as assinaturas digitais
As assinaturas digitais são geradas usando uma Chave secreta de assinatura do URL ou uma chave criptográfica disponível no console do Google Cloud. Ela é essencialmente uma chave privada, compartilhada somente entre você e o Google, e pertence exclusivamente ao seu ID de cliente.
O processo de assinatura usa um algoritmo de criptografia para combinar o URL e a chave secreta compartilhada. Quando você usa a assinatura exclusiva resultante, nossos servidores verificam se os sites que geram solicitações usando seu ID de cliente têm autorização para isso.
Assinar suas solicitações
Estas são as etapas para assinar suas solicitações:
- Etapa 1: gerar a Chave secreta de assinatura do URL
- Etapa 2: criar uma solicitação sem assinatura
- Etapa 3: gerar a solicitação assinada
Etapa 1: gerar a Chave secreta de assinatura do URL
Para usar a Chave secreta de assinatura do URL do projeto, siga estas etapas:
- Acesse a página do ID do cliente no console do Cloud.
- No campo Chave, você encontra a Chave secreta de assinatura do URL do ID do cliente.
Se precisar gerar novamente essa chave, entre em contato com o suporte.
Etapa 2: criar solicitação sem assinatura
Os caracteres não listados na tabela abaixo precisam ser codificados para uso em URL:
Conjunto | de caracteres | Uso em URLs |
---|---|---|
Alfanuméricos | a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 | Strings de texto, uso do esquema (http ), porta (8080 ) etc. |
Não reservados | - _ . ~ | Strings de texto |
Reservados | ! * ' ( ) ; : @ & = + $ , / ? % # [ ] | Caracteres de controle e/ou strings de texto |
O mesmo vale para todos os caracteres no conjunto Reservado, se eles forem transferidos dentro de uma string de texto. Para mais informações, consulte Caracteres especiais.
Gere o URL de solicitação sem assinatura.
Inclua também o ID do cliente no parâmetro client
. Exemplo:
https://maps.googleapis.com/maps/api/staticmap?center=Z%C3%BCrich&size=400x400&client=YOUR_CLIENT_ID
Gerar a solicitação assinada
Para solucionar problemas, você pode gerar uma assinatura digital automaticamente usando o widget Assinar URL agora.
Para solicitações geradas dinamicamente, você precisa da assinatura do lado do servidor, que requer mais algumas etapas intermediárias.
De qualquer forma, haverá um URL de solicitação com um parâmetro signature
anexado ao final. Exemplo:
https://maps.googleapis.com/maps/api/staticmap?center=Z%C3%BCrich&size=400x400&client=YOUR_CLIENT_ID &signature=BASE64_SIGNATURE
-
Remova o esquema do protocolo e as partes do host do URL, deixando apenas o caminho e a consulta:
-
A Chave secreta de assinatura do URL exibida é codificada em um Base64 modificado para URLs.
Como a maioria das bibliotecas criptográficas exige que a chave esteja no formato de bytes brutos, você provavelmente vai precisar decodificar a Chave secreta de assinatura do URL no formato bruto original antes de assinar.
- Assine a solicitação com as partes removidas acima usando HMAC-SHA1.
-
Como a maioria das bibliotecas criptográficas gera uma assinatura no formato de byte bruto, você precisa converter a assinatura binária resultante usando o método Base64 modificado para que os URLs o convertam em algo que possa ser transmitido dentro do URL.
-
Anexe a assinatura codificada com Base64 ao URL original da solicitação não assinada no parâmetro
signature
. Exemplo:https://maps.googleapis.com/maps/api/staticmap?center=Z%C3%BCrich&size=400x400&client=YOUR_CLIENT_ID &signature=BASE64_SIGNATURE
/maps/api/staticmap?center=Z%C3%BCrich&size=400x400&client=YOUR_CLIENT_ID
Se quiser exemplos de como implementar a assinatura de URL usando o código do lado do servidor, consulte Exemplo de código para assinatura de URL abaixo.
Exemplo de código para assinatura de URL
As seções abaixo mostram como implementar a assinatura de URL usando o código do lado do servidor. Os URLs sempre precisam ser assinados no servidor para evitar a exposição da Chave secreta de assinatura do URL aos usuários.
Python
O exemplo abaixo usa bibliotecas Python padrão para assinar um URL. Faça o download do código (link em inglês).
#!/usr/bin/python # -*- coding: utf-8 -*- """ Signs a URL using a URL signing secret """ import hashlib import hmac import base64 import urllib.parse as urlparse def sign_url(input_url=None, secret=None): """ Sign a request URL with a URL signing secret. Usage: from urlsigner import sign_url signed_url = sign_url(input_url=my_url, secret=SECRET) Args: input_url - The URL to sign secret - Your URL signing secret Returns: The signed request URL """ if not input_url or not secret: raise Exception("Both input_url and secret are required") url = urlparse.urlparse(input_url) # We only need to sign the path+query part of the string url_to_sign = url.path + "?" + url.query # Decode the private key into its binary format # We need to decode the URL-encoded private key decoded_key = base64.urlsafe_b64decode(secret) # Create a signature using the private key and the URL-encoded # string using HMAC SHA1. This signature will be binary. signature = hmac.new(decoded_key, str.encode(url_to_sign), hashlib.sha1) # Encode the binary signature into base64 for use within a URL encoded_signature = base64.urlsafe_b64encode(signature.digest()) original_url = url.scheme + "://" + url.netloc + url.path + "?" + url.query # Return signed URL return original_url + "&signature=" + encoded_signature.decode() if __name__ == "__main__": input_url = input("URL to Sign: ") secret = input("URL signing secret: ") print("Signed URL: " + sign_url(input_url, secret))
Java
O exemplo abaixo usa a classe java.util.Base64
disponível desde o JDK 1.8. Talvez as versões mais antigas precisem usar o Apache Commons ou similar.
Faça o download do código (link em inglês).
import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Base64; // JDK 1.8 only - older versions may need to use Apache Commons or similar. import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.net.URL; import java.io.BufferedReader; import java.io.InputStreamReader; public class UrlSigner { // Note: Generally, you should store your private key someplace safe // and read them into your code private static String keyString = "YOUR_PRIVATE_KEY"; // The URL shown in these examples is a static URL which should already // be URL-encoded. In practice, you will likely have code // which assembles your URL from user or web service input // and plugs those values into its parameters. private static String urlString = "YOUR_URL_TO_SIGN"; // This variable stores the binary key, which is computed from the string (Base64) key private static byte[] key; public static void main(String[] args) throws IOException, InvalidKeyException, NoSuchAlgorithmException, URISyntaxException { BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); String inputUrl, inputKey = null; // For testing purposes, allow user input for the URL. // If no input is entered, use the static URL defined above. System.out.println("Enter the URL (must be URL-encoded) to sign: "); inputUrl = input.readLine(); if (inputUrl.equals("")) { inputUrl = urlString; } // Convert the string to a URL so we can parse it URL url = new URL(inputUrl); // For testing purposes, allow user input for the private key. // If no input is entered, use the static key defined above. System.out.println("Enter the Private key to sign the URL: "); inputKey = input.readLine(); if (inputKey.equals("")) { inputKey = keyString; } UrlSigner signer = new UrlSigner(inputKey); String request = signer.signRequest(url.getPath(),url.getQuery()); System.out.println("Signed URL :" + url.getProtocol() + "://" + url.getHost() + request); } public UrlSigner(String keyString) throws IOException { // Convert the key from 'web safe' base 64 to binary keyString = keyString.replace('-', '+'); keyString = keyString.replace('_', '/'); System.out.println("Key: " + keyString); // Base64 is JDK 1.8 only - older versions may need to use Apache Commons or similar. this.key = Base64.getDecoder().decode(keyString); } public String signRequest(String path, String query) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException, URISyntaxException { // Retrieve the proper URL components to sign String resource = path + '?' + query; // Get an HMAC-SHA1 signing key from the raw key bytes SecretKeySpec sha1Key = new SecretKeySpec(key, "HmacSHA1"); // Get an HMAC-SHA1 Mac instance and initialize it with the HMAC-SHA1 key Mac mac = Mac.getInstance("HmacSHA1"); mac.init(sha1Key); // compute the binary signature for the request byte[] sigBytes = mac.doFinal(resource.getBytes()); // base 64 encode the binary signature // Base64 is JDK 1.8 only - older versions may need to use Apache Commons or similar. String signature = Base64.getEncoder().encodeToString(sigBytes); // convert the signature to 'web safe' base 64 signature = signature.replace('+', '-'); signature = signature.replace('/', '_'); return resource + "&signature=" + signature; } }
Node JS
O exemplo abaixo usa módulos nativos do Node para assinar um URL. Faça o download do código (link em inglês).
'use strict' const crypto = require('crypto'); const url = require('url'); /** * Convert from 'web safe' base64 to true base64. * * @param {string} safeEncodedString The code you want to translate * from a web safe form. * @return {string} */ function removeWebSafe(safeEncodedString) { return safeEncodedString.replace(/-/g, '+').replace(/_/g, '/'); } /** * Convert from true base64 to 'web safe' base64 * * @param {string} encodedString The code you want to translate to a * web safe form. * @return {string} */ function makeWebSafe(encodedString) { return encodedString.replace(/\+/g, '-').replace(/\//g, '_'); } /** * Takes a base64 code and decodes it. * * @param {string} code The encoded data. * @return {string} */ function decodeBase64Hash(code) { // "new Buffer(...)" is deprecated. Use Buffer.from if it exists. return Buffer.from ? Buffer.from(code, 'base64') : new Buffer(code, 'base64'); } /** * Takes a key and signs the data with it. * * @param {string} key Your unique secret key. * @param {string} data The url to sign. * @return {string} */ function encodeBase64Hash(key, data) { return crypto.createHmac('sha1', key).update(data).digest('base64'); } /** * Sign a URL using a secret key. * * @param {string} path The url you want to sign. * @param {string} secret Your unique secret key. * @return {string} */ function sign(path, secret) { const uri = url.parse(path); const safeSecret = decodeBase64Hash(removeWebSafe(secret)); const hashedSignature = makeWebSafe(encodeBase64Hash(safeSecret, uri.path)); return url.format(uri) + '&signature=' + hashedSignature; }
C#
No exemplo abaixo, a biblioteca padrão System.Security.Cryptography
é usada para assinar uma solicitação de URL.
É preciso converter a codificação Base64 padrão para implementar uma versão compatível com URL.
Faça o download do código (link em inglês).
using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Web; namespace SignUrl { public struct GoogleSignedUrl { public static string Sign(string url, string keyString) { ASCIIEncoding encoding = new ASCIIEncoding(); // converting key to bytes will throw an exception, need to replace '-' and '_' characters first. string usablePrivateKey = keyString.Replace("-", "+").Replace("_", "/"); byte[] privateKeyBytes = Convert.FromBase64String(usablePrivateKey); Uri uri = new Uri(url); byte[] encodedPathAndQueryBytes = encoding.GetBytes(uri.LocalPath + uri.Query); // compute the hash HMACSHA1 algorithm = new HMACSHA1(privateKeyBytes); byte[] hash = algorithm.ComputeHash(encodedPathAndQueryBytes); // convert the bytes to string and make url-safe by replacing '+' and '/' characters string signature = Convert.ToBase64String(hash).Replace("+", "-").Replace("/", "_"); // Add the signature to the existing URI. return uri.Scheme+"://"+uri.Host+uri.LocalPath + uri.Query +"&signature=" + signature; } } class Program { static void Main() { // Note: Generally, you should store your private key someplace safe // and read them into your code const string keyString = "YOUR_PRIVATE_KEY"; // The URL shown in these examples is a static URL which should already // be URL-encoded. In practice, you will likely have code // which assembles your URL from user or web service input // and plugs those values into its parameters. const string urlString = "YOUR_URL_TO_SIGN"; string inputUrl = null; string inputKey = null; Console.WriteLine("Enter the URL (must be URL-encoded) to sign: "); inputUrl = Console.ReadLine(); if (inputUrl.Length == 0) { inputUrl = urlString; } Console.WriteLine("Enter the Private key to sign the URL: "); inputKey = Console.ReadLine(); if (inputKey.Length == 0) { inputKey = keyString; } Console.WriteLine(GoogleSignedUrl.Sign(inputUrl,inputKey)); } } }
Exemplos em outras linguagens
Confira outros exemplos de linguagens no projeto url-signing (link em inglês).
Solução de problemas
Se a solicitação inclui uma assinatura inválida, a API retorna um erro HTTP 403 (Forbidden)
. Esse erro provavelmente vai ocorrer se o segredo de assinatura usado não estiver vinculado ao ID do cliente transmitido ou se a entrada não ASCII não for codificada por URL antes de assinar.
Para solucionar o problema, copie o URL da solicitação, remova o parâmetro de consulta signature
e gere novamente uma assinatura válida seguindo as instruções abaixo:
Para gerar uma assinatura digital com seu ID do cliente usando o widget Assinar URL agora, faça o seguinte:
- Busque a chave secreta de assinatura do URL do ID do cliente, conforme descrito na Etapa 1: gerar a Chave secreta de assinatura do URL.
- No campo URL, cole o URL da Etapa 2: criar solicitação sem assinatura.
- No campo Chave secreta de assinatura do URL, cole a chave da etapa 2.
Uma assinatura digital é gerada com base no URL de solicitação sem assinatura e na chave secreta de assinatura, além de ser anexada ao URL original. - O URL assinado digitalmente aparecerá no campo Seu URL assinado.