ตรวจสอบคำขอ Places API ด้วย Firebase AppCheck และ reCAPTCHA

1. ก่อนเริ่มต้น

หากต้องการตรวจสอบความถูกต้องของผู้ใช้ที่โต้ตอบกับเว็บแอปพลิเคชัน คุณจะต้องติดตั้งใช้งาน Firebase App Check โดยใช้ประโยชน์จากโทเค็น JWT ของ reCAPTCHA เพื่อยืนยันเซสชันของผู้ใช้ การตั้งค่านี้จะช่วยให้คุณจัดการคำขอจากแอปพลิเคชันไคลเอ็นต์ไปยัง Places API (ใหม่) ได้อย่างปลอดภัย

b40cfddb731786fa.png

ลิงก์สด

สิ่งที่คุณจะสร้าง

คุณจะสร้างเว็บแอปที่แสดงแผนที่เมื่อโหลดเพื่อสาธิตการทำงานนี้ นอกจากนี้ยังจะสร้างโทเค็น reCAPTCHA โดยใช้ Firebase SDK อย่างไม่เปิดเผยด้วย จากนั้นระบบจะส่งโทเค็นนี้ไปยังเซิร์ฟเวอร์ Node.js ซึ่ง Firebase จะตรวจสอบโทเค็นก่อนที่จะดำเนินการตามคำขอไปยัง Places API

หากโทเค็นถูกต้อง Firebase App Check จะจัดเก็บโทเค็นนั้นจนกว่าจะหมดอายุ ซึ่งจะช่วยให้ไม่ต้องสร้างโทเค็นใหม่สำหรับคำขอของไคลเอ็นต์ทุกครั้ง หากโทเค็นไม่ถูกต้อง ระบบจะแจ้งให้ผู้ใช้ทำการยืนยัน reCAPTCHA อีกครั้งเพื่อรับโทเค็นใหม่

2. ข้อกำหนดเบื้องต้น

คุณจะต้องทำความคุ้นเคยกับรายการด้านล่างเพื่อทำ Codelab นี้ให้เสร็จสมบูรณ์ daea823b6bc38b67.png

ผลิตภัณฑ์ Google Cloud ที่จำเป็น

  • Google Cloud Firebase App Check: ฐานข้อมูลสําหรับการจัดการโทเค็น
  • Google reCAPTCHA: การสร้างและการยืนยันโทเค็น ซึ่งเป็นเครื่องมือที่ใช้แยกแยะมนุษย์ออกจากบ็อตในเว็บไซต์ โดยจะวิเคราะห์พฤติกรรมของผู้ใช้ แอตทริบิวต์ของเบราว์เซอร์ และข้อมูลเครือข่ายเพื่อสร้างคะแนนที่บ่งบอกถึงความเป็นไปได้ที่ผู้ใช้จะเป็นบอท หากคะแนนสูงพอ ระบบจะถือว่าผู้ใช้เป็นมนุษย์และไม่จำเป็นต้องดำเนินการใดๆ เพิ่มเติม หากคะแนนต่ำ ระบบอาจแสดงปริศนา CAPTCHA เพื่อยืนยันตัวตนของผู้ใช้ วิธีนี้รบกวนผู้ใช้น้อยกว่าวิธีการ CAPTCHA แบบเดิม จึงทำให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ราบรื่นยิ่งขึ้น
  • (ไม่บังคับ) Google Cloud App Engine: สภาพแวดล้อมในการติดตั้งใช้งาน

ผลิตภัณฑ์ Google Maps Platform ที่จำเป็น

ใน Codelab นี้ คุณจะได้ใช้ผลิตภัณฑ์ Google Maps Platform ต่อไปนี้

ข้อกำหนดอื่นๆ สำหรับ Codelab นี้

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

  • บัญชี Google Cloud Platform ที่เปิดใช้การเรียกเก็บเงิน
  • คีย์ API ของ Google Maps Platform ที่เปิดใช้ Maps JavaScript API และ Places
  • ความรู้พื้นฐานเกี่ยวกับ JavaScript, HTML และ CSS
  • ความรู้พื้นฐานเกี่ยวกับ Node.js
  • โปรแกรมแก้ไขข้อความหรือ IDE ที่คุณเลือก

3. เตรียมตัว

ตั้งค่า Google Maps Platform

หากยังไม่มีบัญชี Google Cloud Platform และโปรเจ็กต์ที่เปิดใช้การเรียกเก็บเงิน โปรดดูคำแนะนำการเริ่มต้นใช้งาน Google Maps Platform เพื่อสร้างบัญชีสำหรับการเรียกเก็บเงินและโปรเจ็กต์

  1. ใน Cloud Console ให้คลิกเมนูแบบเลื่อนลงของโปรเจ็กต์ แล้วเลือกโปรเจ็กต์ที่ต้องการใช้สำหรับ Codelab นี้

e7ffad81d93745cd.png

  1. เปิดใช้ Google Maps Platform APIs และ SDK ที่จำเป็นสำหรับ Codelab นี้ใน Google Cloud Marketplace โดยทำตามขั้นตอนในวิดีโอนี้หรือเอกสารประกอบนี้
  2. สร้างคีย์ API ในหน้าข้อมูลเข้าสู่ระบบของ Cloud Console คุณสามารถทำตามขั้นตอนในวิดีโอนี้หรือเอกสารประกอบนี้ คำขอทั้งหมดที่ส่งไปยัง Google Maps Platform ต้องมีคีย์ API

ข้อมูลรับรองเริ่มต้นของแอปพลิเคชัน

คุณจะใช้ Firebase Admin SDK เพื่อโต้ตอบกับโปรเจ็กต์ Firebase รวมถึงส่งคำขอไปยัง Places API และจะต้องระบุข้อมูลเข้าสู่ระบบที่ถูกต้องเพื่อให้ทำงานได้

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

คำจำกัดความ: ข้อมูลรับรองเริ่มต้นของแอปพลิเคชัน (ADC) คือกลไกที่ Google Cloud มีไว้เพื่อตรวจสอบสิทธิ์แอปพลิเคชันโดยอัตโนมัติโดยไม่ต้องจัดการข้อมูลรับรองอย่างชัดแจ้ง โดยจะค้นหาข้อมูลเข้าสู่ระบบในตำแหน่งต่างๆ (เช่น ตัวแปรสภาพแวดล้อม ไฟล์บัญชีบริการ หรือเซิร์ฟเวอร์ข้อมูลเมตาของ Google Cloud) และใช้ข้อมูลเข้าสู่ระบบแรกที่พบ

  • ในเทอร์มินัล ให้ใช้คำสั่งด้านล่างซึ่งอนุญาตให้แอปพลิเคชันเข้าถึงทรัพยากร Google Cloud ได้อย่างปลอดภัยในนามของผู้ใช้ที่เข้าสู่ระบบในปัจจุบัน
gcloud auth application-default login
  • คุณจะสร้างไฟล์ .env ที่รูทซึ่งระบุตัวแปรโปรเจ็กต์ Google Cloud ดังนี้
GOOGLE_CLOUD_PROJECT="your-project-id"

สร้างบัญชีบริการ

  • แท็บ Google Maps Platform > "+สร้างข้อมูลเข้าสู่ระบบ" > บัญชีบริการ
  • เพิ่มบทบาทผู้ดูแลระบบ App Check ของ Firebase จากนั้นป้อนชื่อบัญชีบริการที่คุณเพิ่งพิมพ์ เช่น firebase-appcheck-codelab@yourproject.iam.gserviceaccount.com

ข้อมูลเข้าสู่ระบบ

  • คลิกบัญชีบริการที่สร้างขึ้น
  • ไปที่แท็บคีย์เพื่อสร้างคีย์ > JSON > บันทึกข้อมูลเข้าสู่ระบบ JSON ที่ดาวน์โหลด ย้ายไฟล์ xxx.json ที่ดาวน์โหลดอัตโนมัติไปยังโฟลเดอร์รูท
  • (บทถัดไป) ตั้งชื่อให้ถูกต้องเป็นเซิร์ฟเวอร์ไฟล์ nodejs server.js (firebase-credentials.json)

4. การผสานรวม Firebase App Check

คุณจะได้รับรายละเอียดการกำหนดค่า Firebase และคีย์ข้อมูลลับ reCAPTCHA

คุณจะวางข้อมูลดังกล่าวลงในแอปพลิเคชันเดโมและเริ่มเซิร์ฟเวอร์

สร้างแอปพลิเคชันใน Firebase

เลือกโปรเจ็กต์ Google Cloud ที่สร้างไว้แล้ว (คุณอาจต้องระบุ "การเลือกทรัพยากรหลัก")

a6d171c6d7e98087.png a16010ba102cc90b.png

  • เพิ่มแอปพลิเคชันจากเมนูด้านซ้ายบน (ฟันเฟือง)

18e5a7993ad9ea53.png 4632158304652118.png

โค้ดการเริ่มต้น Firebase

  • บันทึกโค้ดการเริ่มต้น Firebase เพื่อวางใน script.js (บทถัดไป) สำหรับฝั่งไคลเอ็นต์

f10dcf6f5027e9f0.png

  • ลงทะเบียนแอปเพื่อให้ Firebase ใช้โทเค็น reCAPTCHA v3 ได้

https://console.firebase.google.com/u/0/project/YOUR_PROJECT/appcheck/apps

da7efe203ce4142c.png

  • เลือก reCAPTCHA → สร้างคีย์ในเว็บไซต์ reCAPTCHA (กำหนดค่าโดเมนที่ถูกต้อง: localhost สำหรับการพัฒนาแอป)

b47eab131617467.png e6bddef9d5cf5460.png

  • วางข้อมูลลับ reCAPTCHA ใน Firebase AppCheck

a63bbd533a1b5437.png

  • สถานะแอปควรเปลี่ยนเป็นสีเขียว

4f7962b527b78ee5.png

5. แอปพลิเคชันสาธิต

  • เว็บแอปฝั่งไคลเอ็นต์: ไฟล์ HTML, JavaScript, CSS
  • เซิร์ฟเวอร์: ไฟล์ Node.js
  • สภาพแวดล้อม (.env): คีย์ API
  • การกำหนดค่า (app.yaml): การตั้งค่าการติดตั้งใช้งาน Google App Engine

การตั้งค่า Node.js

  • ไปที่: เปิดเทอร์มินัลแล้วไปที่ไดเรกทอรีรากของโปรเจ็กต์ที่โคลน
  • ติดตั้ง Node.js (หากจำเป็น): เวอร์ชัน 18 ขึ้นไป
node -v  # Check installed version
  • เริ่มต้นโปรเจ็กต์: เรียกใช้คำสั่งต่อไปนี้เพื่อเริ่มต้นโปรเจ็กต์ Node.js ใหม่โดยปล่อยให้การตั้งค่าทั้งหมดเป็นค่าเริ่มต้น
npm init 
  • ติดตั้งการอ้างอิง: ใช้คำสั่งต่อไปนี้เพื่อติดตั้งการอ้างอิงของโปรเจ็กต์ที่จำเป็น
npm install @googlemaps/places firebase-admin express axios dotenv

การกำหนดค่า: ตัวแปรสภาพแวดล้อมสำหรับโปรเจ็กต์ Google Cloud

  • การสร้างไฟล์สภาพแวดล้อม: สร้างไฟล์ชื่อ .env ในไดเรกทอรีรากของโปรเจ็กต์ ไฟล์นี้จะจัดเก็บข้อมูลการกำหนดค่าที่ละเอียดอ่อนและไม่ควรส่งไปยังการควบคุมเวอร์ชัน
  • ป้อนตัวแปรสภาพแวดล้อม: เปิดไฟล์ .env แล้วเพิ่มตัวแปรต่อไปนี้ โดยแทนที่ตัวยึดตำแหน่งด้วยค่าจริงจากโปรเจ็กต์ Google Cloud
# Google Cloud Project ID
GOOGLE_CLOUD_PROJECT="your-cloud-project-id"

# reCAPTCHA Keys (obtained in previous steps) 
RECAPTCHA_SITE_KEY="your-recaptcha-site-key"
RECAPTCHA_SECRET_KEY="your-recaptcha-secret-key"

# Maps Platform API Keys (obtained in previous steps)
PLACES_API_KEY="your-places-api-key"
MAPS_API_KEY="your-maps-api-key"

6. ภาพรวมของโค้ด

index.html

  • โหลดไลบรารี Firebase เพื่อสร้างโทเค็นในแอป
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Places API with AppCheck</title>
  <style></style>  </head>
<body>
  <div id="map"></div>

    <!-- Firebase services -->
  <script src="https://www.gstatic.com/firebasejs/9.15.0/firebase-app-compat.js"></script>
  <script src="https://www.gstatic.com/firebasejs/9.15.0/firebase-app-check-compat.js"></script>
  
  <script type="module" src="./script.js"></script> 
  <link rel="stylesheet" href="./style.css">
</body>
</html>

script.js

  • ดึงข้อมูลคีย์ API: ดึงคีย์ API สำหรับ Google Maps และ Firebase App Check จากเซิร์ฟเวอร์แบ็กเอนด์
  • เริ่มต้น Firebase: ตั้งค่า Firebase สำหรับการตรวจสอบสิทธิ์และความปลอดภัย (แทนที่การกำหนดค่า → ดูบทที่ 4)

ระยะเวลาที่โทเค็น Firebase App Check ใช้ได้ ซึ่งมีตั้งแต่ 30 นาทีถึง 7 วัน จะได้รับการกำหนดค่าภายในคอนโซล Firebase และไม่สามารถเปลี่ยนแปลงได้โดยการพยายามบังคับให้รีเฟรชโทเค็น

  • เปิดใช้งาน App Check: เปิดใช้ Firebase App Check เพื่อยืนยันความถูกต้องของคำขอขาเข้า
  • โหลด Google Maps API: โหลดไลบรารี JavaScript ของ Google Maps แบบไดนามิกเพื่อแสดงแผนที่
  • เริ่มต้นแผนที่: สร้าง Google Maps โดยมีตำแหน่งเริ่มต้นเป็นศูนย์กลาง
  • จัดการการคลิกแผนที่: ตรวจหาการคลิกบนแผนที่และอัปเดตจุดศูนย์กลางตามนั้น
  • ค้นหา Places API: ส่งคำขอไปยัง API แบ็กเอนด์ (/api/data) เพื่อดึงข้อมูลเกี่ยวกับสถานที่ (ร้านอาหาร สวนสาธารณะ บาร์) ใกล้กับตำแหน่งที่คลิก โดยใช้ Firebase App Check เพื่อการให้สิทธิ์
  • แสดงเครื่องหมาย: วางแผนที่ข้อมูลที่ดึงมาบนแผนที่เป็นเครื่องหมาย โดยแสดงชื่อและไอคอน
let mapsApiKey, recaptchaKey; // API keys
let currentAppCheckToken = null; // AppCheck token

async function init() {
  try {
    await fetchConfig(); // Load API keys from .env variable

    /////////// REPLACE with your Firebase configuration details
    const firebaseConfig = {
      apiKey: "AIza.......",
      authDomain: "places.......",
      projectId: "places.......",
      storageBucket: "places.......",
      messagingSenderId: "17.......",
      appId: "1:175.......",
      measurementId: "G-CPQ.......",
    };
    /////////// REPLACE 

    // Initialize Firebase and App Check
    await firebase.initializeApp(firebaseConfig);
    await firebase.appCheck().activate(recaptchaKey);

    // Get the initial App Check token
    currentAppCheckToken = await firebase.appCheck().getToken();

    // Load the Maps JavaScript API dynamically
    const scriptMaps = document.createElement("script");
    scriptMaps.src = `https://maps.googleapis.com/maps/api/js?key=${mapsApiKey}&libraries=marker,places&v=beta`;
    scriptMaps.async = true;
    scriptMaps.defer = true;
    scriptMaps.onload = initMap; // Create the map after the script loads
    document.head.appendChild(scriptMaps);
  } catch (error) {
    console.error("Firebase initialization error:", error);
    // Handle the error appropriately (e.g., display an error message)
  }
}
window.onload = init()

// Fetch configuration data from the backend API
async function fetchConfig() {
  const url = "/api/config";

  try {
    const response = await fetch(url);
    const config = await response.json();
    mapsApiKey = config.mapsApiKey;
    recaptchaKey = config.recaptchaKey;
  } catch (error) {
    console.error("Error fetching configuration:", error);
    // Handle the error (e.g., show a user-friendly message)
  }
}

// Initialize the map when the Maps API script loads
let map; // Dynamic Map
let center = { lat: 48.85557501, lng: 2.34565006 };
function initMap() {
  map = new google.maps.Map(document.getElementById("map"), {
    center: center,
    zoom: 13,
    mapId: "b93f5cef6674c1ff",
    zoomControlOptions: {
      position: google.maps.ControlPosition.RIGHT_TOP,
    },
    streetViewControl: false,
    mapTypeControl: false,
    clickableIcons: false,
    fullscreenControlOptions: {
      position: google.maps.ControlPosition.LEFT_TOP,
    },
  });

  // Initialize the info window for markers
  infoWindow = new google.maps.InfoWindow({});

  // Add a click listener to the map
  map.addListener("click", async (event) => {
    try {
      // Get a fresh App Check token on each click
      const appCheckToken = await firebase.appCheck().getToken();
      currentAppCheckToken = appCheckToken;

      // Update the center for the Places API query
      center.lat = event.latLng.lat();
      center.lng = event.latLng.lng();

      // Query for places with the new token and center
      queryPlaces();
    } catch (error) {
      console.error("Error getting App Check token:", error);
    }
  });
}

function queryPlaces() {
  const url = '/api/data'; // "http://localhost:3000/api/data"

  const body = {
    request: {
      includedTypes: ['restaurant', 'park', 'bar'],
      excludedTypes: [],
      maxResultCount: 20,
      locationRestriction: {
        circle: {
          center: {
            latitude: center.lat,
            longitude: center.lng,
          },
          radius: 4000,
        },
      },
    },
  };

  // Provides token to the backend using header: X-Firebase-AppCheck

  fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Firebase-AppCheck': currentAppCheckToken.token,
    },
    body: JSON.stringify(body),
  })
    .then((response) => response.json())
    .then((data) => {
      // display if response successful
      displayMarkers(data.places);
    })
    .catch((error) => {
      alert('No places');
      // eslint-disable-next-line no-console
      console.error('Error:', error);
    });
}


//// display places markers on map
...

server.js

  • โหลดตัวแปรสภาพแวดล้อม (คีย์ API, รหัสโปรเจ็กต์ Google) จากไฟล์ .env
  • เริ่มเซิร์ฟเวอร์เพื่อรอรับคำขอใน http://localhost:3000
  • เริ่มต้น Firebase Admin SDK โดยใช้ข้อมูลรับรองเริ่มต้นของแอปพลิเคชัน (ADC)
  • รับโทเค็น reCAPTCHA จาก script.js
  • ตรวจสอบความถูกต้องของโทเค็นที่ได้รับ
  • หากโทเค็นถูกต้อง จะส่งคำขอ POST ไปยัง Google Places API พร้อมพารามิเตอร์การค้นหาที่รวมไว้
  • ประมวลผลและส่งคืนการตอบกลับจาก Places API ไปยังไคลเอ็นต์
const express = require('express');
const axios = require('axios');

const admin = require('firebase-admin');

// .env variables
require('dotenv').config();

// Store sensitive API keys in environment variables
const recaptchaSite = process.env.RECAPTCHA_SITE_KEY;
const recaptchaSecret = process.env.RECAPTCHA_SECRET_KEY;
const placesApiKey = process.env.PLACES_API_KEY;
const mapsApiKey = process.env.MAPS_API_KEY;

// Verify environment variables loaded (only during development)
console.log('recaptchaSite:', recaptchaSite, '\n');
console.log('recaptchaSecret:', recaptchaSecret, '\n');

const app = express();
app.use(express.json());

// Firebase Admin SDK setup with Application Default Credentials (ADC)
const { GoogleAuth } = require('google-auth-library');
admin.initializeApp({
  // credential: admin.credential.applicationDefault(), // optional: explicit ADC
});

// Main API Endpoint 
app.post('/api/data', async (req, res) => {
  const appCheckToken = req.headers['x-firebase-appcheck'];

  console.log("\n", "Token", "\n", "\n", appCheckToken, "\n")

  try {
    // Verify Firebase App Check token for security
    const appCheckResult = await admin.appCheck().verifyToken(appCheckToken);

    if (appCheckResult.appId) {
      console.log('App Check verification successful!');
      placesQuery(req, res);
    } else {
      console.error('App Check verification failed.');
      res.status(403).json({ error: 'App Check verification failed.' });
    }
  } catch (error) {
    console.error('Error verifying App Check token:', error);
    res.status(500).json({ error: 'Error verifying App Check token.' });
  }
});

// Function to query Google Places API
async function placesQuery(req, res) {
  console.log('#################################');
  console.log('\n', 'placesApiKey:', placesApiKey, '\n');

  const queryObject = req.body.request;
  console.log('\n','Request','\n','\n', queryObject, '\n')

  const headers = {
    'Content-Type': 'application/json',
    'X-Goog-FieldMask': '*',
    'X-Goog-Api-Key': placesApiKey,
    'Referer': 'http://localhost:3000',  // Update for production(ie.: req.hostname)
  };

  const myUrl = 'https://places.googleapis.com/v1/places:searchNearby';

  try {
    // Authenticate with ADC
    const auth = new GoogleAuth();
    const { credential } = await auth.getApplicationDefault();

    const response = await axios.post(myUrl, queryObject, { headers, auth: credential });
    
    console.log('############### SUCCESS','\n','\n','Response','\n','\n', );
    const myBody = response.data;
    myBody.places.forEach(place => {
      console.log(place.displayName); 
    });
    res.json(myBody); // Use res.json for JSON data
  } catch (error) {
    console.log('############### ERROR');
    // console.error(error); // Log the detailed error for debugging
    res.status(error.response.status).json(error.response.data); // Use res.json for errors too
  }
}

// Configuration endpoint (send safe config data to the client)
app.get('/api/config', (req, res) => {
  res.json({
    mapsApiKey: process.env.MAPS_API_KEY, 
    recaptchaKey: process.env.RECAPTCHA_SITE_KEY, 
  });
});

// Serve static files
app.use(express.static('static'));

// Start the server
const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server listening on port ${port}`, '\n');
});

7. เรียกใช้แอปพลิเคชัน

จากสภาพแวดล้อมที่เลือก ให้เรียกใช้เซิร์ฟเวอร์จากเทอร์มินัล แล้วไปที่ http://localhost:3000

npm start 

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

ดูรายละเอียดเกี่ยวกับฟังก์ชันของเซิร์ฟเวอร์และการตอบกลับคำขอการค้นหาในบริเวณใกล้เคียงของ Places API ได้ในบันทึกของเซิร์ฟเวอร์

การแก้ปัญหา:

ตรวจสอบว่ารหัสโปรเจ็กต์ Google สอดคล้องกันในการตั้งค่า

  • ในไฟล์ .env (ตัวแปร GOOGLE_CLOUD_PROJECT)
  • ในการกำหนดค่า gcloud ของเทอร์มินัล
gcloud config set project your-project-id
  • ในการตั้งค่า reCAPTCHA

e6bddef9d5cf5460.png

  • ในการตั้งค่า Firebase

7e17bfbcb8007763.png

อื่นๆ

  • สร้างโทเค็นการแก้ไขข้อบกพร่องที่ใช้แทนคีย์เว็บไซต์ reCAPTCHA ภายใน script.js เพื่อวัตถุประสงค์ในการทดสอบและการแก้ปัญหา

9c0beb760d13faef.png

try {
 // Initialize Firebase first
 await firebase.initializeApp(firebaseConfig);
  // Set the debug token
  if (window.location.hostname === 'localhost') { // Only in development
    await firebase.appCheck().activate(
      'YOUR_DEBUG_FIREBASE_TOKEN', // Replace with the token from the console
      true // Set to true to indicate it's a debug token
      );
  } else {
      // Activate App Check
      await firebase.appCheck().activate(recaptchaKey);
}
  • การพยายามตรวจสอบสิทธิ์ที่ไม่สำเร็จหลายครั้ง เช่น การใช้คีย์เว็บไซต์ reCAPTCHA ที่ไม่ถูกต้อง อาจทำให้เกิดการจำกัดอัตราชั่วคราว
FirebaseError: AppCheck: Requests throttled due to 403 error. Attempts allowed again after 01d:00m:00s (appCheck/throttled).

ข้อมูลเข้าสู่ระบบ ADC

  • ตรวจสอบว่าคุณใช้บัญชี gcloud ที่ถูกต้อง
gcloud auth login 
  • ตรวจสอบว่าได้ติดตั้งไลบรารีที่จำเป็นแล้ว
npm install @googlemaps/places firebase-admin
  • ตรวจสอบว่าโหลดไลบรารี Firebase ใน server.js แล้ว
const {GoogleAuth} = require('google-auth-library');
gcloud auth application-default login
  • แอบอ้างเป็นบุคคลอื่น: บันทึกข้อมูลเข้าสู่ระบบ ADC แล้ว
gcloud auth application-default login --impersonate-service-account your_project@appspot.gserviceaccount.com
  • สุดท้ายให้ทดสอบ ADC ในเครื่อง โดยบันทึกสคริปต์ต่อไปนี้เป็น test.js และเรียกใช้ในเทอร์มินัล node test.js
const {GoogleAuth} = require('google-auth-library');

async function requestTestADC() {
 try {
   // Authenticate using Application Default Credentials (ADC)
   const auth = new GoogleAuth();
   const {credential} = await auth.getApplicationDefault();

   // Check if the credential is successfully obtained
   if (credential) {
     console.log('Application Default Credentials (ADC) loaded successfully!');
     console.log('Credential:', credential); // Log the credential object
   } else {
     console.error('Error: Could not load Application Default Credentials (ADC).');
   }

   // ... rest of your code ...

 } catch (error) {
   console.error('Error:', error);
 }
}

requestTestADC();

8. แค่นี้ก็เรียบร้อย เก่งมาก

ขั้นตอนการติดตามผล

การติดตั้งใช้งานใน App Engine:

  • เตรียมโปรเจ็กต์สำหรับการติดตั้งใช้งานใน Google App Engine โดยทำการเปลี่ยนแปลงการกำหนดค่าที่จำเป็น
  • ใช้gcloudเครื่องมือบรรทัดคำสั่งหรือคอนโซล App Engine เพื่อทำให้แอปพลิเคชันใช้งานได้

ปรับปรุงการตรวจสอบสิทธิ์ Firebase:

  • โทเค็นเริ่มต้นเทียบกับโทเค็นที่กำหนดเอง: ใช้โทเค็นที่กำหนดเองของ Firebase เพื่อใช้บริการ Firebase ในเชิงลึกยิ่งขึ้น
  • อายุการใช้งานโทเค็น: ตั้งค่าอายุการใช้งานโทเค็นที่เหมาะสม โดยตั้งค่าให้สั้นลงสำหรับการดำเนินการที่มีความละเอียดอ่อน (โทเค็น Firebase ที่กำหนดเองสูงสุด 1 ชั่วโมง) และตั้งค่าให้ยาวขึ้นสำหรับเซสชันทั่วไป (โทเค็น reCAPTCHA: 30 นาทีถึง 7 ชั่วโมง)
  • สำรวจทางเลือกอื่นแทน reCAPTCHA: ตรวจสอบว่า DeviceCheck (iOS), SafetyNet (Android) หรือ App Attest เหมาะกับความต้องการด้านความปลอดภัยของคุณหรือไม่

ผสานรวมผลิตภัณฑ์ Firebase:

  • Realtime Database หรือ Firestore: หากแอปพลิเคชันต้องการการซิงค์ข้อมูลแบบเรียลไทม์หรือความสามารถในการทำงานแบบออฟไลน์ ให้ผสานรวมกับ Realtime Database หรือ Firestore
  • Cloud Storage: ใช้ Cloud Storage เพื่อจัดเก็บและแสดงเนื้อหาที่ผู้ใช้สร้างขึ้น เช่น รูปภาพหรือวิดีโอ
  • การตรวจสอบสิทธิ์: ใช้ประโยชน์จากการตรวจสอบสิทธิ์ Firebase เพื่อสร้างบัญชีผู้ใช้ จัดการเซสชันการเข้าสู่ระบบ และจัดการการรีเซ็ตรหัสผ่าน

ขยายไปยังอุปกรณ์เคลื่อนที่:

  • Android และ iOS: หากวางแผนที่จะมีแอปบนอุปกรณ์เคลื่อนที่ ให้สร้างเวอร์ชันสำหรับทั้งแพลตฟอร์ม Android และ iOS
  • Firebase SDK: ใช้ Firebase SDK สำหรับ Android และ iOS เพื่อผสานรวมฟีเจอร์ของ Firebase เข้ากับแอปบนอุปกรณ์เคลื่อนที่ได้อย่างราบรื่น