Maps Static API:取得 API 金鑰和簽章

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

選擇驗證方法

如要使用 Google 地圖平台,您必須使用下列任一方法來驗證要求:「API 金鑰搭配數位簽章」「用戶端 ID 搭配數位簽章」。為減少在程式碼中使用用戶端 ID,請盡量使用 API 金鑰搭配數位簽名。

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

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

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

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

使用 API 金鑰和數位簽章進行驗證

建立 API 金鑰

您的專案必須有至少一個相關聯的 API 金鑰。

取得 API 金鑰的方法如下:

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

  4. 按一下選單按鈕 ,然後選取 [Google 地圖平台] > [憑證]
  5. 在「憑證」頁面上,按一下 [建立憑證] > [API 金鑰]
    「建立的 API 金鑰」對話方塊會顯示新建立的 API 金鑰 (加密字串)。
  6. 按一下 [關閉]
    新建立的 API 金鑰便會出現在「憑證」頁面的「API 金鑰」下方。

將 API 金鑰加進要求中

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

https://maps.googleapis.com/maps/api/staticmap?center=40.714%2c%20-73.998&zoom=12&size=400x400&key=YOUR_API_KEY

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

限制 API 金鑰

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

限制 API 金鑰的方法如下:

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

    前往「憑證」頁面

  2. 選取您要設定限制的 API 金鑰。畫面隨即顯示 API 金鑰屬性頁面。
  3. 在「金鑰限制」下方,設定下列限制:
    • 應用程式限制:
      1. 如要接受由您提供的網站清單中所列的要求,請從「應用程式限制」清單中選取 [HTTP 參照網址 (網站)]
      2. 指定一或多個參照網址網站。舉例來說,*.google.com 接受網址以 google.com 結尾的所有網站 (例如 https://developers.google.com)。

        注意事項:file:// 參照網址需要使用特殊表示法才能新增至金鑰限制。您必須將「file://」部分替換為「__file_url__」,參照網址才能新增至金鑰限制。例如,「file:///path/to/」的格式應為「__file_url__//path/to/*」。啟用 file:// 參照網址後,建議您定期檢查使用情形,確保與您的預期一致。

    • API 限制:
      1. 按一下 [限制金鑰]
      2. 從「選取 API」下拉式選單中選取 [Google 地圖平台]。 如果選單未列出 Google 地圖平台,您必須先加以啟用
  4. 如要完成變更,請按一下 [儲存]

產生數位簽章

使用 key 參數 (含 API 金鑰) 向 Google 地圖平台發出的要求中,也必須包含 signature 參數 (其中包含必須以共用網址簽署密鑰產生的數位簽章)。您可在 Google Cloud Console 上取得共用密鑰。

簽署程序會使用加密演算法將網址與共用密鑰結合。我們的伺服器會根據產生的專屬簽章進行驗證,確認使用您 API 金鑰產生要求的所有網站都已獲得授權。

建立數位簽章的流程有兩個步驟:

步驟 1:取得網址簽署密鑰

您可在 Cloud Console 上取得加密編譯網址簽署密鑰。密鑰又稱為私密金鑰,是以網址適用的修改版 Base64 進行編碼。這組密鑰是專屬於您的 API 金鑰,由您與 Google 共用。請妥善保管網址簽署密鑰。這組密鑰不得用於任何要求、儲存在任何網站上,或張貼到任何公開論壇;否則任何人只要取得這個網址簽署密鑰,都能假冒您的身分提出要求。

在 Cloud Console 的這個頁面中取得網址簽署密鑰。重要事項:請選取您購買付費方案時建立的專案。

或者,您也可以按照下列步驟查看網址簽署密鑰:

  1. 前往 Cloud Console
  2. 按一下專案下拉式選單,然後選取您購買付費方案時建立的專案。專案名稱開頭為 Google Maps API for Business 或 Google Maps for Work 或 Google Maps
  3. 在「資訊主頁」頁面的 API 清單中,按一下 Google 地圖平台的名稱。畫面隨即會開啟「總覽」分頁,並顯示該 API 的詳細資料。
  4. 按一下 [網址簽署密鑰] 分頁標籤。

如要取得新的網址簽署密鑰,請按一下 [重新產生密鑰]。新密鑰產生後 24 小時,上一組密鑰隨即失效,而包含舊密鑰的要求也會一樣在 24 小時後失效。

步驟 2:產生數位簽章

如要為要求建立數位簽章,請參閱「使用 API 金鑰產生數位簽章」一節。

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

用戶端 ID 和加密編譯金鑰簡介

購買 Google 地圖平台付費方案授權後,您會收到 Google 寄送的歡迎電子郵件,內含您的用戶端 ID私人加密編譯金鑰

  • 您的用戶端 ID 將用來存取 Google 地圖平台付費方案的一些特殊功能。請將下方範例中的 YOUR_CLIENT_ID 替換成您在歡迎電子郵件中取得的用戶端 ID。所有用戶端 ID 開頭的前置字串都是 gme-

  • 您的私人加密編譯金鑰會用來產生不重複的數位簽章。在下方的程式碼範例中,請將 SIGNATURE 替換成您專屬的數位簽章。詳情請參閱使用用戶端 ID 產生數位簽章

    <img src="https://maps.googleapis.com/maps/api/staticmap
      ?center=-15.800513,-47.91378
      &zoom=11
      &size=300x300
      &client=YOUR_CLIENT_ID
      &signature=SIGNATURE">

如果您遺失用戶端 ID 或私人加密編譯金鑰,只要登入 Google Cloud Console,然後按一下頁面左側連結的 [地圖:管理用戶端 ID] 即可取回。

報表的選用參數

使用用戶端 ID 進行 API 驗證時,您可以使用下列選用參數:

  • channel 可用來在報表中區隔不同的管道,藉此提供額外的報表詳細資料。詳情請參閱付費方案報表總覽

產生數位簽章

如要為要求建立數位簽章,請參閱「使用用戶端 ID 產生數位簽章」一節。

數位簽章

數位簽章的運作方式

您必須使用 Google Cloud Platform Console 提供的加密編譯網址簽署密鑰,才能產生數位簽章。密鑰又稱為私密金鑰,是以網址適用的修改版 Base64 進行編碼。這組密鑰專屬於您的 API 金鑰,由您與 Google 共用。

簽署程序會使用加密演算法將網址與共用密鑰結合。我們的伺服器會根據產生的專屬簽章進行驗證,確認使用您 API 金鑰產生要求的所有網站都已獲得授權。

您可以使用 API 金鑰用戶端 ID 產生數位簽章。

使用 API 金鑰產生數位簽章

請按照以下步驟建立數位簽名,與 API 金鑰搭配使用:

  1. 建立不含簽章的要求網址,並請務必在 key 參數中加入 API 金鑰。請注意,所有非標準字元都必須經過網址編碼處理。例如:

    https://maps.googleapis.com/maps/api/staticmap?center=40.714%2c%20-73.998&zoom=12&size=400x400&key=YOUR_API_KEY

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

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

    /maps/api/staticmap?center=40.714%2c%20-73.998&zoom=12&size=400x400&key=YOUR_API_KEY

  3. 從 Cloud Console 擷取您的網址簽署密鑰 (該密鑰是以網址適用的修改版 Base64 進行編碼),並使用 HMAC-SHA1 演算法簽署前個步驟產生的網址 (請參閱「取得網址簽署密鑰」一節)。

    您可能需要將密鑰解碼為原始的二進位格式。請注意,在大部分的加密編譯程式庫中,最終的簽章會採用二進位格式。

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

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

  5. 將產生的簽章新增至要求網址中 (置於 signature 參數內)。例如:

    https://maps.googleapis.com/maps/api/staticmap?center=40.714%2c%20-73.998&zoom=12&size=400x400&key=YOUR_API_KEY&signature=BASE64_SIGNATURE

如需使用伺服器端程式碼導入網址簽署的做法範例,請參閱「網址簽署的程式碼範例」。

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

使用用戶端 ID 產生數位簽章

使用 client 參數向 Static Maps API 送出的要求也需要數位 signature;您可以使用歡迎電子郵件中提供的私人加密編譯金鑰來產生這個簽章。

簽署過程會使用加密演算法來組合網址和金鑰,我們的伺服器會藉由專屬簽章,驗證是否所有使用您用戶端 ID 產生要求的網站都已獲得授權。此外,每個網址也都有專屬簽章,確保只有在已要求產生新簽章的情況下,才能修改使用您用戶端 ID 的要求。

您的私人加密編譯金鑰

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

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

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

使用用戶端 ID 產生數位簽章

如果嘗試以無效的簽章存取 Static Maps API,就會發生 HTTP 403 (禁止) 錯誤。為應用程式改用網址簽署時,請務必進行測試,確保簽章可發出有效的要求;請先測試原始網址是否有效,以及是否可以產生正確的簽章。

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

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

    https://maps.googleapis.com/maps/api/staticmap?center=40.714%2c%20-73.998&zoom=12&size=400x400&client=clientID

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

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

    /maps/api/staticmap?center=40.714%2c%20-73.998&zoom=12&size=400x400&client=clientID

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

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

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

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

    https://maps.googleapis.com/maps/api/staticmap?center=40.714%2c%20-73.998&zoom=12&size=400x400&client=clientID&signature=base64signature

如需使用伺服器端程式碼導入網址簽署的做法範例,請參閱「網址簽署的程式碼範例」。

如要立即簽署網址,請在下方輸入網址和網址簽署密鑰。網址必須採用前文步驟 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 地圖平台會傳回 HTTP 403 (Forbidden) 錯誤。

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

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