使用 Firebase 驗證使用者

區域 ID

REGION_ID 是 Google 根據您在建立應用程式時選取的地區所指派的縮寫代碼。此代碼不對應至國家/地區或省份,即使部分區域 ID 可能與常用的國家/地區和省份代碼相似。如果是 2020 年 2 月後建立的應用程式,App Engine 網址會包含 REGION_ID.r。如果是這段時間前建立的現有應用程式,網址可選擇是否包含地區 ID。

進一步瞭解區域 ID

將使用者登入流程新增至使用 Firebase 驗證的網路服務。

在本指南的這一步驟中,您會更新網路服務來驗證使用者,並在使用者完成驗證後,擷取及顯示使用者自己的資訊。請注意,在這個步驟中,網站要求時間仍為全域,而非使用者專屬。

事前準備

如果您已完成本指南先前提過的所有步驟,請跳過本節。 否則,請完成下列其中一個步驟:

  • 建構 Python 3 應用程式開始,完成這個步驟之前的所有步驟。

  • 如果您已經有Google Cloud 專案,接下來可以下載網路服務的複本並新增 Firebase:

    1. 使用 Git 下載範例應用程式存放區:

      git clone https://github.com/GoogleCloudPlatform/python-docs-samples 

      您也可以下載 zip 格式的範例,然後解壓縮該檔案。

    2. 前往包含上一步驟檔案複本的目錄:

      cd python-docs-samples/appengine/standard_python3/building-an-app/building-an-app-2 
    3. 將 Firebase 新增至 Google Cloud 專案和網路服務

新增 Firebase 驗證方法

Firebase 提供 JavaScript 方法與變數,您可用來設定網路服務的登入行為。針對此網路服務,您可以新增登出函式、設定登入 UI 的變數,以及新增使用者登入或登出時控制變更內容的函式。

如要新增驗證流程所需的行為,請將 static/script.js 檔案的目前事件監聽器方法替換為下列程式碼:

window.addEventListener('load', function () {   document.getElementById('sign-out').onclick = function () {     firebase.auth().signOut();   };    // FirebaseUI config.   var uiConfig = {     signInSuccessUrl: '/',     signInOptions: [       // Comment out any lines corresponding to providers you did not check in       // the Firebase console.       firebase.auth.GoogleAuthProvider.PROVIDER_ID,       firebase.auth.EmailAuthProvider.PROVIDER_ID,       //firebase.auth.FacebookAuthProvider.PROVIDER_ID,       //firebase.auth.TwitterAuthProvider.PROVIDER_ID,       //firebase.auth.GithubAuthProvider.PROVIDER_ID,       //firebase.auth.PhoneAuthProvider.PROVIDER_ID      ],     // Terms of service url.     tosUrl: '<your-tos-url>'   };    firebase.auth().onAuthStateChanged(function (user) {     if (user) {       // User is signed in, so display the "sign out" button and login info.       document.getElementById('sign-out').hidden = false;       document.getElementById('login-info').hidden = false;       console.log(`Signed in as ${user.displayName} (${user.email})`);       user.getIdToken().then(function (token) {         // Add the token to the browser's cookies. The server will then be         // able to verify the token against the API.         // SECURITY NOTE: As cookies can easily be modified, only put the         // token (which is verified server-side) in a cookie; do not add other         // user information.         document.cookie = "token=" + token;       });     } else {       // User is signed out.       // Initialize the FirebaseUI Widget using Firebase.       var ui = new firebaseui.auth.AuthUI(firebase.auth());       // Show the Firebase login button.       ui.start('#firebaseui-auth-container', uiConfig);       // Update the login state indicators.       document.getElementById('sign-out').hidden = true;       document.getElementById('login-info').hidden = true;       // Clear the token cookie.       document.cookie = "token=";     }   }, function (error) {     console.log(error);     alert('Unable to log in: ' + error)   }); });

請注意,onAuthStateChanged() 方法會控制使用者登入或登出時的變更內容,並將使用者的 ID 權杖儲存為 Cookie。這個 ID 權杖是 Firebase 在使用者成功登入時自動產生的專屬權杖,伺服器會使用這個權杖驗證使用者。

更新網路服務以使用權杖

接下來,使用專屬的 Firebase ID 憑證在伺服器上驗證使用者,然後對使用者的憑證進行解密,以便將資料列印後回傳給使用者。

如要使用 Firebase ID 憑證:

  1. 擷取、驗證並解密位在 main.py 檔案的 root 方法中的權杖。

    from flask import Flask, render_template, request from google.auth.transport import requests from google.cloud import datastore import google.oauth2.id_token  firebase_request_adapter = requests.Request() @app.route("/") def root():     # Verify Firebase auth.     id_token = request.cookies.get("token")     error_message = None     claims = None     times = None      if id_token:         try:             # Verify the token against the Firebase Auth API. This example             # verifies the token on each page load. For improved performance,             # some applications may wish to cache results in an encrypted             # session store (see for instance             # http://flask.pocoo.org/docs/1.0/quickstart/#sessions).             claims = google.oauth2.id_token.verify_firebase_token(                 id_token, firebase_request_adapter             )         except ValueError as exc:             # This will be raised if the token is expired or any other             # verification checks fail.             error_message = str(exc)          # Record and fetch the recent times a logged-in user has accessed         # the site. This is currently shared amongst all users, but will be         # individualized in a following step.         store_time(datetime.datetime.now(tz=datetime.timezone.utc))         times = fetch_times(10)      return render_template(         "index.html", user_data=claims, error_message=error_message, times=times     )  
  2. 確認您的 requirements.txt 檔案包含所有必要的依附元件:

    Flask==3.0.0 google-cloud-datastore==2.15.1 google-auth==2.17.3 requests==2.28.2 

測試網路服務

請在虛擬環境中在本機執行網路服務,藉此進行測試:

  1. 在專案的主要目錄中執行下列指令,以安裝新的依附元件並執行網路服務。 如果您尚未設定本機測試用的虛擬環境,請參閱測試您的網路服務

    pip install -r requirements.txt python main.py 
  2. 請在網路瀏覽器中輸入下列網址,以便查看網路服務:

    http://localhost:8080 

部署您的網路服務

現在您已在本機執行驗證,便可將網路服務重新部署至 App Engine。

您可以在 app.yaml 檔案所在的專案根目錄中執行下列指令:

gcloud app deploy 

系統會自動將所有流量轉送至您部署的新版本。

如要進一步瞭解如何管理版本,請參閱管理服務和版本

查看服務

如要快速啟動瀏覽器並前往 https://PROJECT_ID.REGION_ID.r.appspot.com 使用網路服務,請執行下列指令:

gcloud app browse 

後續步驟

現在您已經設定使用者驗證,可以開始瞭解如何更新網路服務,將已驗證使用者的資料個人化。