Elevation API:取得 API 金鑰

注意事項:Google 地圖平台付費方案不再開放註冊或提供給新客戶。

選擇驗證方法

如要使用 Google 地圖平台,您必須使用 API 金鑰或是用戶端 ID,搭配數位簽章來驗證要求。

可選用的驗證方法取決於您的授權類型:

  • 採用付費方案的客戶可以使用 API 金鑰或是用戶端 ID 搭配數位簽章。
  • 使用舊版授權的客戶則必須使用用戶端 ID 與數位簽章進行驗證。

在判斷要採用哪種驗證方法時,您可以考量下列這幾點:

  • 使用 API 金鑰進行驗證 (付費方案)
    如果使用 API 金鑰來驗證要求,您可以:
    • 在 Google Cloud Console 的「API」頁面管理所有的 API。
    • 在 Cloud Console 的「API」頁面查看即時使用資料和 30 天的歷來使用資料。
    • channel 參數加進要求中,以便查看更詳細的使用情況報表。
    • 透過 Google Cloud Console 查看內含超過 30 天資料的使用情況報表。
  • 使用用戶端 ID 和數位簽章進行驗證 (付費方案或舊版授權)
    如果使用用戶端 ID 和數位簽章來驗證要求,您可以:
    • channel 參數加進要求中,以便查看更詳細的使用情況報表。
    • 透過 Cloud Console 查看內含超過 30 天資料的使用情況報表。
    • 使用 Maps JavaScript API 適用的地圖 Analytics (分析) 工具。

進一步瞭解付費方案客戶可用的報表

使用 API 金鑰進行驗證

取得 API 金鑰

API 金鑰是一組專屬 ID,用來驗證與專案相關的使用權限與帳單處理要求。

取得 API 金鑰的方法如下:

  1. 在 Cloud Console 的專案選取器頁面中,選取或建立您想新增 API 金鑰的 Google Cloud 專案。

    前往專案選取器頁面

    注意事項:如要使用方案的完整功能,付費客戶應使用與付費帳戶連結的專案。購買授權後,您會收到以下列格式編寫的付費資產名稱:gme-[company] > proj-[number] ([type])。為確保您存取的是正確的專案,請透過 console.cloud.google.com/project/number (將 number 替換成專案編號) 以「專案擁有者身分」登入 Cloud Console。 您可以在歡迎信中查看專案擁有者是誰。

  2. 前往「Google 地圖平台」>「憑證」頁面。

    前往「憑證」頁面

  3. 在「憑證」頁面上,按一下 [建立憑證] > [API 金鑰]
    「建立的 API 金鑰」對話方塊會顯示您新建立的 API 金鑰。
  4. 按一下 [關閉]
    新建立的 API 金鑰便會出現在「憑證」頁面的「API 金鑰」下方。
    (在實際工作環境中使用新建立的金鑰前,記得要先限制 API 金鑰。)

將 API 金鑰加進要求中

每個 Google 地圖平台要求都必須包含 API 金鑰。請將以下範例中的 YOUR_API_KEY 替換成您的 API 金鑰。

https://maps.googleapis.com/maps/api/elevation/json?locations=39.7391536,-104.9847034&key=YOUR_API_KEY

使用 API 金鑰的要求必須透過 HTTPS 傳送,而對於使用用戶端 ID 的要求,則不強制但建議採用 HTTPS。此外,應用程式要求如果含有敏感的使用者資料 (如使用者所在位置),也必須採用 HTTPS。

限制 API 金鑰

限制 API 金鑰可確保只有經授權的要求才能使用 API 金鑰,進而提升您應用程式的安全性。我們極力建議您按照操作說明設定 API 金鑰的限制。詳情請參閱 API 安全性最佳做法

限制 API 金鑰的方法如下:

  1. 前往「Google 地圖平台」>「憑證」頁面。

    前往「憑證」頁面

  2. 選取您要設定限制的 API 金鑰。畫面隨即顯示 API 金鑰屬性頁面。
  3. 在「金鑰限制」下方,設定下列限制:
    • 應用程式限制:
      1. 如要接受來自您提供的清單中網路伺服器 IP 位址提出的要求,請從「應用程式限制」清單中選取 [IP 位址 (網路伺服器和 Cron 工作等)]
      2. 指定一個 IPv4 或 IPv6 位址,或是採用 CIDR 標記法的子網路 (例如 192.168.0.0/22)。如果您還需要輸入其他項目,系統會在您新增上述項目後顯示新的對話方塊。
    • API 限制:
      1. 按一下 [限制金鑰]
      2. 從「選取 API」下拉式選單中選取 [Google 地圖平台]。 如果選單未列出 Google 地圖平台,您必須先加以啟用
  4. 如要完成變更,請按一下 [儲存]

使用用戶端 ID 搭配數位簽章進行驗證

購買 Google 地圖平台付費方案授權後,您會收到 Google 寄送的歡迎電子郵件,內含您的用戶端 ID 及私人加密編譯金鑰 (可用來產生您專屬的數位簽章)。

您必須將用戶端 ID 與專屬數位簽章傳遞給以下程式碼範例中的 clientsignature 參數。

    https://maps.googleapis.com/maps/api/elevation/json
      ?locations=39.7391536,-104.9847034
      &client=YOUR_CLIENT_ID
      &signature=SIGNATURE
  • YOUR_CLIENT_ID 替換成歡迎電子郵件中隨附的用戶端 ID。

    您的用戶端 ID 會以 gme- 字元開頭。

  • SIGNATURE 替換成您專屬的數位簽章 (請參閱產生數位簽章)。

注意事項:

  • 使用用戶端 ID 搭配數位簽章驗證 Google 地圖平台時,您也可以選擇使用 channel 參數接收詳細的使用報表。詳情請參閱付費方案報表簡介
  • 如果您原先使用 API 金鑰進行驗證,但現在要改用用戶端 ID,必須將要求中的 key 參數移除。Google Maps API 網路服務會拒絕同時使用用戶端 ID 與 API 金鑰送出的要求

產生數位簽章

Google 地圖平台付費方案客戶向 Elevation API 送出要求時,必須提供數位 signature。透過歡迎電子郵件中隨附的私人加密編譯金鑰即可產生這個簽章 (詳情請見「進一步瞭解私人加密編譯金鑰」一節的說明)。

請按照下列步驟為您的要求產生數位簽章。

  1. 建立不含簽章的要求網址,並務必加上 client 參數。請注意,所有非標準字元都需要經過網址編碼處理:

    https://maps.googleapis.com/maps/api/elevation/json?locations=39.7391536,-104.9847034&client=clientID

    注意事項:所有 Google 服務都要求採用 UTF-8 字元編碼 (也就是以隱含方式納入 ASCII)。如果您的應用程式運作時會使用其他字元集,請確認網址是以 UTF-8 字元建立,且經過妥善的網址編碼處理。

  2. 去除要求中的網域部分,只留下路徑及查詢:

    /maps/api/elevation/json?locations=39.7391536,-104.9847034&client=clientID

  3. 擷取您的私密金鑰 (該金鑰是以網址適用的修改版 Base64 進行編碼),並使用 HMAC-SHA1 演算法簽署前個步驟產生的網址。您可能需要將此金鑰解碼為原始的二進位格式。請注意,在大部分的加密編譯程式庫中,最終的簽章是採用二進位格式。

    注意事項:修改版 Base64 網址編碼會將標準 Base64 編碼的 +/ 字元分別替換成 -_,因此這類 Base64 簽章不需要再進行網址編碼處理。

  4. 使用網址適用的修改版 Base64 為產生的二進位簽章進行編碼,將此簽章轉換為可在網址內傳送的物件。

  5. 將此簽章附加至網址 (置於 signature 參數內):

    https://maps.googleapis.com/maps/api/elevation/json?locations=39.7391536,-104.9847034&client=clientID&signature=base64signature

注意事項:

  • 我們的伺服器會藉由專屬簽章,驗證是否所有使用您用戶端 ID 產生要求的網站都已獲得授權。此外,每個網址也都有專屬簽章,確保只有在已要求產生新簽章的情況下,才能修改使用您用戶端 ID 的要求。
  • 如果嘗試以無效的簽章存取 Elevation API,就會發生 HTTP 403 (禁止) 錯誤。如要讓應用程式改用網址簽署,請務必先進行測試,確保簽章可發出有效的要求。請先測試原始網址是否有效,以及是否可以產生正確的簽章。
  • 如需使用伺服器端程式碼導入網址簽署的做法範例,請參閱「網址簽署的程式碼範例」。

如要立即簽署網址,請在下方輸入網址和網址簽署密鑰。網址必須採用前文步驟 1 所述的格式,並且經過網址編碼處理。

網址簽署程式碼範例

後續章節會說明使用伺服器端程式碼導入網址簽署的方式。網址應一律在伺服器端簽署,以避免向其他使用者暴露您的加密編譯金鑰。

Python

以下範例使用標準 Python 程式庫簽署網址 (下載程式碼)。

#!/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

以下範例使用 JDK 1.8 以上版本提供的 java.util.Base64 類別;如果您使用較舊版本,建議使用 Apache Commons 或類似程式碼 (下載程式碼)。

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

以下範例使用原生 Node 模組簽署網址 (下載程式碼)。

'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#

以下範例使用預設的 System.Security.Cryptography 程式庫簽署網址要求。請注意,我們必須轉換預設的 Base64 編碼,才能導入安全網址版本 (下載程式碼)。

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

針對測試部分,您可以試試看以下網址及私密金鑰能否產生正確的簽章。請注意,這組私密金鑰僅供測試,實際上無法通過任何 Google 服務的驗證。

  • 網址https://maps.googleapis.com/maps/api/geocode/json?address=New+York&client=clientID
  • 私密金鑰vNIXE0xscrmjlyV-12Nj_BvUPaw=
  • 要簽署的網址部分/maps/api/geocode/json?address=New+York&client=clientID
  • 簽章chaRF2hTJKOScPr-RQCEhZbSzIE=
  • 完整的已簽署網址https://maps.googleapis.com/maps/api/geocode/json?address=New+York&client=clientID&signature=chaRF2hTJKOScPr-RQCEhZbSzIE=

其他程式語言範例

如需其他程式語言範例,請參閱網址簽署專案。

進一步瞭解私人加密編譯金鑰

系統會使用您的用戶端 ID 核發私人加密編譯網址簽署金鑰,該金鑰是您和 Google 之間的「共同密鑰」。這組簽署金鑰為您獨有,且專屬於您的用戶端 ID。因此,請妥善保管簽署金鑰。這組金鑰不得用於任何要求、儲存在任何網站上,或張貼到任何公開論壇;否則凡是能取得該簽署金鑰的使用者,都可以假冒您的身分提出要求。

注意事項:這組私人加密編譯簽署金鑰與 Google Cloud Console 核發的 API 金鑰「不」一樣。

如果您遺失了私人加密編譯金鑰,請登入 Cloud Console,然後按一下 [地圖:管理用戶端 ID] 以擷取該金鑰。

排解驗證相關問題

如果要求格式錯誤或提供的簽章無效,Google 地圖平台會傳回 HTTP 403 (Forbidden) 錯誤。

如要排解個別網址的問題,您可以使用網址簽署偵錯工具。此工具可以讓您快速驗證網址和應用程式產生的簽章。

除了上述方法外,付費方案客戶也可以登入 Cloud Console,然後選取 [資源] > [Google 地圖平台付費方案線上工具] > [網路服務和 Image API 的網址簽署偵錯工具],接著解決個別網址的問題