ใช้ลายเซ็นดิจิทัล

ลงนามคำขอแบบดิจิทัลด้วยคีย์ API

อาจต้องใช้ลายเซ็นดิจิทัลนอกเหนือจากคีย์ API เพื่อตรวจสอบสิทธิ์คำขอ ทั้งนี้ขึ้นอยู่กับการใช้งานของคุณ ดูบทความต่อไปนี้

วิธีการทำงานของลายเซ็นดิจิทัล

ลายเซ็นดิจิทัลสร้างขึ้นโดยใช้ข้อมูลลับในการรับรอง URL ซึ่งมีอยู่ใน Google Cloud Console ข้อมูลลับนี้เป็นคีย์ส่วนตัวที่มีการแชร์กันระหว่างคุณและ Google เท่านั้น และเป็นคีย์เฉพาะสำหรับโปรเจ็กต์ของคุณ

กระบวนการลงนามจะใช้อัลกอริทึมการเข้ารหัสเพื่อรวม URL และข้อมูลลับที่ใช้ร่วมกัน ลายเซ็นที่ไม่ซ้ำกันที่ได้จะช่วยให้เซิร์ฟเวอร์ของเรายืนยันได้ว่าเว็บไซต์ใดก็ตามที่สร้างคำขอโดยใช้คีย์ API ของคุณได้รับอนุญาตให้ดำเนินการดังกล่าว

จำกัดคำขอที่ไม่ได้ลงนาม

วิธีตรวจสอบว่าคีย์ API ยอมรับเฉพาะคำขอที่ลงนามแล้วเท่านั้น

  1. ไปที่หน้าโควต้า Google Maps Platform ใน Cloud Console
  2. คลิกเมนูแบบเลื่อนลงของโปรเจ็กต์และเลือกโปรเจ็กต์เดียวกับที่คุณใช้เมื่อสร้างคีย์ API สำหรับแอปพลิเคชันหรือเว็บไซต์
  3. เลือก Street View Static API จากเมนูแบบเลื่อนลง API
  4. ขยายส่วนคำขอที่ไม่ได้ลงนาม
  5. ในตารางชื่อโควต้า ให้คลิกปุ่มแก้ไขข้างโควต้าที่ต้องการแก้ไข ตัวอย่างเช่น คำขอที่ไม่ได้ลงนามต่อวัน
  6. อัปเดตขีดจำกัดโควต้าในแผงแก้ไขขีดจำกัดโควต้า
  7. เลือกบันทึก

กำลังลงชื่อคำขอของคุณ

การเซ็นชื่อคำขอประกอบด้วยขั้นตอนต่อไปนี้

ขั้นตอนที่ 1: รับข้อมูลลับในการรับรอง URL

ในการรับข้อมูลลับในการรับรอง URL โปรเจ็กต์ ให้ทำดังนี้

  1. ไปที่หน้าข้อมูลเข้าสู่ระบบ Google Maps Platform ใน Cloud Console
  2. เลือกเมนูแบบเลื่อนลงของโปรเจ็กต์และเลือกโปรเจ็กต์เดียวกับที่คุณใช้เมื่อสร้างคีย์ API สำหรับ Street View Static API
  3. เลื่อนลงไปที่การ์ด Secret Generator ช่องข้อมูลลับปัจจุบันมีข้อมูลลับในการรับรอง URL ปัจจุบัน
  4. หน้านี้ยังมีวิดเจ็ตลงนาม URL เลยที่ให้คุณลงนามในคำขอ API แบบคงที่ของ Street View ได้���ดยอัตโนมัติโดยใช้ข้อมูลลับในการรับรองป��จจุบัน เลื่อนลงไปที่การ์ดลงนาม URL เลยเพื่อเข้าถึง

หากต้องการรับข้อมูลลับใน URL Signing ใหม่ ให้เลือกสร้างข้อมูลลับใหม่ ข้อมูลลับก่อนหน้าจะหมดอายุภายใน 24 ชั่วโมงหลังจากที่คุณสร้างข้อมูลลับใหม่ หลังจากผ่านไป 24 ชั่วโมงแล้ว คำขอที่มีข้อมูลลับเดิมจะใช้ไม่ได้อีกต่อไป

ขั้นตอนที่ 2: สร้างคำขอที่ไม่ได้ลงนาม

อักขระที่ไม่แสดงในตารางด้านล่างจะต้องเข้ารหัส URL

ตั้งค่าตัวละครการใช้ URL
ตัวอักษรและตัวเลข 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 X Y Z 0 1 2 3 4 สตริงข้อความ การใช้รูปแบบ (http) พอร์ต (8080) เป็นต้น
ไม่ได้จอง - _ ~ สตริงข้อความ
จองแล้ว ! * ' ( ) ; : @ & = + $ , / ? % # [ ] อักขระควบคุมและ/หรือสตริงข้อความ

เช่นเดียวกันกับอักขระใดๆ ในชุดสงวนไว้ หากมีการส่งผ่านภายในสตริงข้อความ ดูข้อมูลเพิ่มเติมได้ที่สัญลักษณ์พิเศษ

สร้าง URL คำขอที่ไม่ได้ลงนามโดยไม่มีลายเซ็น โปรดดูวิธีการในเอกสารสำหรับนักพัฒนาซอฟต์แวร์ต่อไปนี้

ตรวจสอบว่าได้ใส่คีย์ API ในพารามิเตอร์ key ด้วย เช่น

https://maps.googleapis.com/maps/api/streetview?location=Z%C3%BCrich&size=400x400&key=YOUR_API_KEY

สร้างคำขอที่ลงนามแล้ว

สำหรับการใช้งานแบบครั้งเดียว เช่น การโฮสต์ Maps Static API หรือ Street View Static API ได้ง่ายๆ ในหน้าเว็บหรือเพื่อวัตถุประสงค์ในการแก้ปัญหา คุณอาจสร้างลายเซ็นดิจิทัลโดยอัตโนมัติโดยใช้วิดเจ็ตลงนาม URL เลยที่พร้อมใช้งาน

สำหรับคำขอที่สร้างแบบไดนามิก คุณต้องมีการลงชื่อฝั่งเซิร์ฟเวอร์ ซึ่งต้องมีขั้นตอนกลางเพิ่มเติมเล็กน้อย

ไม่ว่าจะด้วยวิธีใด คุณควร URL คำขอที่มีพารามิเตอร์ signature ต่อท้าย เช่น

https://maps.googleapis.com/maps/api/streetview?location=Z%C3%BCrich&size=400x400&key=YOUR_API_KEY
&signature=BASE64_SIGNATURE
การใช้วิดเจ็ต "ลงชื่อเข้าใช้ URL เลย"

หากต้องการสร้างลายเซ็นดิจิทัลด้วยคีย์ API โดยใช้วิดเจ็ตลงนาม URL เลยใน Google Cloud Console ให้ทำดังนี้

  1. ค้นหาวิดเจ็ตลงนาม URL เลยตามที่อธิบายไว้ในขั้นตอนที่ 1: รับข้อมูลลับในการรับรอง URL
  2. ในช่อง URL ให้วาง URL คำขอที่ไม่ได้ลงนามจากขั้นตอนที่ 2: สร้างคำขอที่ไม่ได้ลงนาม
  3. ช่อง URL ที่ลงชื่อของคุณที่ปรากฏขึ้นจะมี URL ที่ลงชื่อแบบดิจิทัลของคุณ และอย่าลืมทำสำเนา
สร้างลายเซ็นดิจิทัลฝั่งเซิร์ฟเวอร์

เมื่อเทียบกับวิดเจ็ตลงนาม URL เลย คุณจะต้องดำเนินการเพิ่มเติมอีก 2-3 ข้อเมื่อสร้างลายเซ็นดิจิทัลฝั่งเซิร์ฟเวอร์

  1. ตัดรูปแบบโปรโตคอลและส่วนของโฮสต์ของ URL ออก เหลือเฉพาะเ��้นทางและคำค้นหา ดังนี้

  2. /maps/api/streetview?location=Z%C3%BCrich&size=400x400&key=YOUR_API_KEY
    
  3. ข้อมูลลับในการลงทะเบียน URL ที่แสดงมีการเข้ารหัสใน Base64 ที่แก้ไขแล้วสําหรับ URL

    เนื่องจากไลบรารีการเข้ารหัสส่วนใหญ่กำหนดให้คีย์อยู่ในรูปแบบไบต์ดิบ คุณอาจต้องถอดรหัสข้อมูลลับในการรับรอง URL ให้เป็นรูปแบบข้อมูลดิบดั้งเดิมก่อนที่จะลงนาม

  4. ลงนามในคำขอที่ถูกตัดสิทธิ์ด้านบนโดยใช้ HMAC-SHA1
  5. เนื่องจากไลบรารีการเข้ารหัสส่วนใหญ่จะสร้างลายเซ็นในรูปแบบไบต์ดิบ คุณจะต้องแปลงลายเซ็นไบนารีที่ได้โดยใช้ Base64 ที่แก้ไขแล้วสำหรับ URL เพื่อแปลงเป็นข้อมูลที่ส่งต่อภายใน URL ได้

  6. เพิ่มลายเซ็นที่เข้ารหัสแบบ Base64 ต่อท้าย URL คำขอเดิมที่ไม่ได้ลงนามในพารามิเตอร์ signature เช่น

    https://maps.googleapis.com/maps/api/streetview?location=Z%C3%BCrich&size=400x400&key=YOUR_API_KEY
    &signature=BASE64_SIGNATURE

สำหรับตัวอย่างที่แสดงวิธีใช้การรับรอง URL โดยใช้โค้ดฝั่งเซิร์ฟเวอร์ โปรดดูตัวอย่างโค้ดสำหรับการลงนาม URL ด้านล่าง

โค้ดตัวอย่างสำหรับการรับรอง URL

ส่วนต่อไปนี้จะแสดงวิธีติดตั้งใช้งาน URL Signing โดยใช้โค้ดฝั่งเซิร์ฟเวอร์ URL ควรมีการรับรองฝั่งเซิร์ฟเวอร์ทุกครั้งเพื่อหลีกเลี่ยงไม่ให้มีการเปิดเผยข้อมูลลับในการรับรอง URL แก่ผู้ใช้

Python

ตัวอย่างด้านล่างใช้ไลบรารี Python มาตรฐานในการลงนาม URL (ดาวน์โหลดโค้ด)

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

ตัวอย่างด้านล่างใช้คลาส java.util.Base64 ที่มีตั้งแต่ JDK 1.8 โดยเวอร์ชันเก่าอาจต้องใช้ 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

ตัวอย่างด้านล่างใช้โมดูลโหนดเนทีฟเพื่อลงนาม URL (ดาวน์โหลดโค้ด)

'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 เริ่มต้นเพื่อลงนามคำขอ URL โปรดทราบว่าเราต้องแปลงการเข้ารหัส Base64 เริ่มต้นเพื่อใช้เวอร์ชันที่ปลอดภัยกับ URL (ดาวน์โหลดโค้ด)

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

ตัวอย่างในภาษาอื่นๆ

ดูตัวอย่างที่ครอบคลุมภาษาอื่นๆ ได้ที่โปรเจ็กต์ url-signing

การแก้ปัญหา

หากคำขอมีลายเซ็นที่ไม่ถูกต้อง API จะแสดงข้อผิดพลาด HTTP 403 (Forbidden) ข้อผิดพลาดนี้อาจเกิดขึ้นมากที่สุดหากข้อมูลลับการลงชื่อที่ใช้ไม่ได้ลิงก์กับคีย์ API ที่ส่งผ่าน หรือเมื่ออินพุตที่ไม่ใช่ ASCII ไม่ได้เข้ารหัส URLก่อนการลงชื่อ

หากต้องการแก้ปัญหา ให้คัดลอก URL คำขอ ตัดพารามิเตอร์การค้นหา signature ออก แล้วสร้างลายเซ็นที่ถูกต้องใหม่โดยทำตามวิธีการด้านล่าง

หากต้องการสร้างลายเซ็นดิจิทัลด้วยคีย์ API โดยใช้วิดเจ็ตลงนาม URL เลยใน Google Cloud Console ให้ทำดังนี้

  1. ค้นหาวิดเจ็ตลงนาม URL เลยตามที่อธิบายไว้ในขั้นตอนที่ 1: รับข้อมูลลับในการรับรอง URL
  2. ในช่อง URL ให้วาง URL คำขอที่ไม่ได้ลงนามจากขั้นตอนที่ 2: สร้างคำขอที่ไม่ได้ลงนาม
  3. ช่อง URL ที่ลงชื่อของคุณที่ปรากฏขึ้นจะมี URL ที่ลงชื่อแบบดิจิทัลของคุณ และอย่าลืมทำสำเนา