实验设置说明和要求
保护您的账号和进度。请务必在无痕浏览器窗口中,使用实验凭证运行此实验。

使用 Apigee X 保護 API

实验 35 分钟 universal_currency_alt 5 积分 show_chart 中级
info 此实验可能会提供 AI 工具来支持您学习。
此内容尚未针对移动设备进行优化。
为获得最佳体验,请在桌面设备上访问通过电子邮件发送的链接。

GSP844

Google Cloud 自學實驗室標誌

總覽

Apigee 是 API 開發與管理平台,能協助您限制 API 存取頻率並提供多項功能,避免內部 API 資料未經授權存取。

在本實驗室中,您將會建立 API,要求使用者須有 OAuth 權杖才能存取。您會使用 SpikeArrest 政策限制應用程式呼叫 API 的頻率,並運用私有變數和資料遮蓋功能,避免對 API 流量偵錯的使用者查看機密資料。

目標

在本實驗室中,您將瞭解如何執行下列工作:

  • 要求 OAuth 權杖來保護 API 存取安全
  • 使用 SpikeArrest 政策,限制整體流量頻率,以及應用程式呼叫 API 的頻率
  • 運用私有變數和資料遮蓋功能,在偵錯 API 呼叫時隱藏機密資料
  • 將後端呼叫限制為指定資源
  • 重新編寫後端錯誤訊息,防止資料外洩

設定和需求

瞭解以下事項後,再點選「Start Lab」按鈕

請詳閱以下操作說明。實驗室活動會計時,且中途無法暫停。點選「Start Lab」後就會開始計時,顯示可使用 Google Cloud 資源的時間。

您將在真正的雲端環境完成實作實驗室活動,而不是模擬或示範環境。為此,我們會提供新的暫時憑證,供您在實驗室活動期間登入及存取 Google Cloud。

為了順利完成這個實驗室,請先確認:

  • 可以使用標準的網際網路瀏覽器 (Chrome 瀏覽器為佳)。
注意事項:請使用無痕模式 (建議選項) 或私密瀏覽視窗執行此實驗室,這可以防止個人帳戶和學員帳戶之間的衝突,避免個人帳戶產生額外費用。
  • 是時候完成實驗室活動了!別忘了,活動一旦開始將無法暫停。
注意事項:務必使用實驗室專用的學員帳戶。如果使用其他 Google Cloud 帳戶,可能會產生額外費用。 注意:建議開啟新的無痕視窗來完成本實驗室。

如何開始研究室及登入 Google Cloud 控制台

  1. 點選「Start Lab」按鈕。如果實驗室會產生費用,畫面上會出現選擇付款方式的對話方塊。左側的「Lab Details」窗格會顯示下列項目:

    • 「Open Google Cloud console」按鈕
    • 剩餘時間
    • 必須在這個研究室中使用的臨時憑證
    • 完成這個實驗室所需的其他資訊 (如有)
  2. 點選「Open Google Cloud console」;如果使用 Chrome 瀏覽器,也能按一下滑鼠右鍵,選取「在無痕視窗中開啟連結」

    接著,實驗室會啟動相關資源,並開啟另一個分頁,顯示「登入」頁面。

    提示:您可以在不同的視窗中並排開啟分頁。

    注意:如果頁面中顯示「選擇帳戶」對話方塊,請點選「使用其他帳戶」
  3. 如有必要,請將下方的 Username 貼到「登入」對話方塊。

    {{{user_0.username | "Username"}}}

    您也可以在「Lab Details」窗格找到 Username。

  4. 點選「下一步」

  5. 複製下方的 Password,並貼到「歡迎使用」對話方塊。

    {{{user_0.password | "Password"}}}

    您也可以在「Lab Details」窗格找到 Password。

  6. 點選「下一步」

    重要事項:請務必使用實驗室提供的憑證,而非自己的 Google Cloud 帳戶憑證。 注意:如果使用自己的 Google Cloud 帳戶來進行這個實驗室,可能會產生額外費用。
  7. 按過後續的所有頁面:

    • 接受條款及細則。
    • 由於這是臨時帳戶,請勿新增救援選項或雙重驗證機制。
    • 請勿申請免費試用。

Google Cloud 控制台稍後會在這個分頁開啟。

注意:如要使用 Google Cloud 產品和服務,請點選「導覽選單」,或在「搜尋」欄位輸入服務或產品名稱。「導覽選單」圖示和搜尋欄位

啟動 Cloud Shell

Cloud Shell 是搭載多項開發工具的虛擬機器,提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作。Cloud Shell 提供指令列存取權,方便您使用 Google Cloud 資源。

  1. 點按 Google Cloud 控制台頂端的「啟用 Cloud Shell」圖示 「啟動 Cloud Shell」圖示

  2. 系統顯示視窗時,請按照下列步驟操作:

    • 繼續操作 Cloud Shell 視窗。
    • 授權 Cloud Shell 使用您的憑證發出 Google Cloud API 呼叫。

連線建立完成即代表已通過驗證,而且專案已設為您的 Project_ID。輸出內容中有一行文字,宣告本工作階段的 Project_ID

Your Cloud Platform project in this session is set to {{{project_0.project_id | "PROJECT_ID"}}}

gcloud 是 Google Cloud 的指令列工具,已預先安裝於 Cloud Shell,並支援 Tab 鍵自動完成功能。

  1. (選用) 您可以執行下列指令來列出使用中的帳戶:
gcloud auth list
  1. 點按「授權」

輸出內容:

ACTIVE: * ACCOUNT: {{{user_0.username | "ACCOUNT"}}} To set the active account, run: $ gcloud config set account `ACCOUNT`
  1. (選用) 您可以使用下列指令來列出專案 ID:
gcloud config list project

輸出內容:

[core] project = {{{project_0.project_id | "PROJECT_ID"}}} 注意:如需 gcloud 的完整說明,請前往 Google Cloud 參閱 gcloud CLI 總覽指南

開啟 Apigee 控制台

如要開啟 Apigee 控制台,請按照下列指示操作:

  • 在 Google Cloud 控制台的「搜尋」欄位輸入 Apigee,然後點選搜尋結果中的「Apigee API 管理平台」

Apigee 控制台隨即開啟,到達網頁會顯示常用位置的快速連結

  • 前往導覽選單 (導覽選單),按一下「Apigee」旁的「收藏」圖示 (收藏圖示)。

這樣 Apigee 就會新增至導覽選單的收藏。

工作 1:使用 Apigee API Proxy 將要求轉送至後端服務

在這項工作中,您會建立 Apigee API Proxy,做為後端服務的門面元件。API Proxy 將使用服務帳戶,向 Cloud Run 服務提供 OpenID Connect 身分識別權杖。

後端服務 simplebank-rest 已建立並部署至 Cloud Run,系統也已為您建立服務帳戶。

建立 Apigee Proxy

  1. 在 Cloud Shell 中,使用下列指令擷取後端服務的網址:

    gcloud run services describe simplebank-rest --platform managed --region {{{project_0.default_region |REGION}}} --format 'value(status.url)'

    請儲存這個網址,建立 API Proxy 時會用到。

  2. 前往 Cloud 控制台的 Apigee UI

  3. 在左側導覽選單中,依序選取「Proxy 開發」>「API Proxy」

  4. 點選「+ Create」,使用 Proxy 精靈建立新的 Proxy。

    您將為後端服務建立反向 Proxy。這個 API Proxy 會按照 OpenAPI 規格建立 API 架構。

  5. 在「Proxy template」方塊中的「OpenAPI spec template」部分,選取「Reverse proxy (Most common)」

  6. 在瀏覽器中開啟下列網址,即可將 OpenAPI 規格的 YAML 檔案下載到電腦,取得 OpenAPI 檔案

    https://storage.googleapis.com/spls/gsp844/simplebank-backend.yaml
  7. 點選「Browse」,然後從電腦中選取 OpenAPI 檔案,再按一下「Next」

  8. 在「Proxy details」指定下列項目:

    屬性
    Proxy 名稱 bank-v1
    基本路徑 /bank/v1
    說明 SimpleBank read-only API
    目標 (現有 API) 後端網址
    注意: 請確認基本路徑為「/bank/v1」,而非「/bank-v1」。

    目標應為您先前在這項工作中擷取的後端網址,大致如下:

    https://simplebank-rest-nu7rb74j5a-uw.a.run.app
  9. 點選「Next」

  10. 其他設定維持預設值,然後點選「Create」

  11. 點選「Develop」分頁標籤。

    注意:處理步驟已新增至 Proxy 端點,每個步驟都會指定 OpenAPI 規格中任一項作業的 HTTP 要求方法和路徑條件。

修改目標來傳送 OpenID Connect 身分識別權杖

由於部署的後端服務要求經過驗證才能存取,您必須具備有效的 OpenID Connect 身分識別權杖,才能呼叫服務。

「HTTPTargetConnection」會指定服務的後端目標。

  1. 在 Proxy 的「Navigator」選單中,點選「Target endpoints」中的「PreFlow」

  2. 找出下列程式碼 (網址部分僅供參考):

    <HTTPTargetConnection> <URL>https://simplebank-rest-zce6j3rjwq-uw.a.run.app</URL> </HTTPTargetConnection> 注意: 如果沒看到 HTTPTargetConnection 區段,請確認您是在「Target Endpoints」中點選「PreFlow」,而非在「Proxy Endpoints」。
  3. 在網址下方新增「Authentication」區段,大致如下:

    <Authentication> <GoogleIDToken> <Audience>AUDIENCE</Audience> </GoogleIDToken> </Authentication>
  4. 將「AUDIENCE」換成「HTTPTargetConnection」區段中的網址值。現在程式碼應大致如下所示,只是 URL 和 Audience 元素要換成實際網址:

    <TargetEndpoint name="default"> <PreFlow name="PreFlow"> <Request/> <Response/> </PreFlow> <Flows/> <PostFlow name="PostFlow"> <Request/> <Response/> </PostFlow> <HTTPTargetConnection> <URL>https://simplebank-rest-zce6j3rjwq-uw.a.run.app</URL> <Authentication> <GoogleIDToken> <Audience>https://simplebank-rest-zce6j3rjwq-uw.a.run.app</Audience> </GoogleIDToken> </Authentication> </HTTPTargetConnection> </TargetEndpoint>
  5. 點選「Save」

點選「Check my progress」,確認目標已達成。 建立 API Proxy

工作 2:將 OAuth 新增到 API Proxy

在這項工作中,您要將 OAuthV2 政策新增到 API Proxy。「OAuthV2」政策會藉由「VerifyJWTAccessToken」作業,在執行階段強制驗證存取權杖,僅允許具備有效 OAuth 存取權杖的應用程式存取 API。

OAuthV2 政策會建立及驗證不透明權杖和 JSON Web Token (JWT)。本實驗室中的 API Proxy 將使用 JWT 做為存取權杖。

您將使用屬性集來儲存建立及驗證 JWT 所需的簽署密鑰。

在屬性集建立簽署密鑰

簽署 JWT 時將使用雜湊型訊息驗證碼 (HMAC),這類加密簽署作業需要密鑰。

  1. 在 Proxy 的「Navigator」選單中,點選「Resources」旁的「+」

  2. 在「Resource Type」下拉式選單中,選取 Property Set

  3. 在「Resource Name」指定 oauth.properties,然後點選「Add」

  4. 在「oauth.properties」程式碼窗格新增下列屬性:

    secret=thisisnotagoodsecret,useabettersecretinproduction

    使用流程變數「propertyset.oauth.secret」,即可在程式碼中存取這個值。

    注意: 屬性集的值會以明文儲存。不過在正式環境,建議將 HMAC 密鑰儲存在加密位置,且務必使用更安全的隨機密鑰。

新增 AssignMessage 政策來擷取屬性集的值

簽署密鑰必須以私有變數提供給 OAuth 政策,但 propertyset.oauth.secret 並非私有變數。AssignMessage 政策會根據屬性集變數建立私有變數。

  1. 在 Proxy 的「Navigator」選單中,依序前往「Proxy endpoints」>「default」,然後點選下方的「PreFlow」

    當要求傳入 API Proxy,首先會執行「預設 Proxy 端點」中的「要求 PreFlow」流程

    「OAuthV2」政策會要求提供密鑰,且會在 API Proxy 的初始階段執行。

  2. 在「Flow」窗格的要求流程中,點選「PreFlow」右側的「+」按鈕

  3. 選取「Create new Policy」,在「Select Policy」下拉式選單的「Mediation」部分選取「Assign Message」,然後將「Display Name」和「Name」設為 AM-GetSecret

  4. 點選「Add」,然後在「Navigator」選單中的「Policies」下方,按一下 AM-GetSecret

    「Code」窗格會顯示「AssignMessage」政策設定。

  5. 將政策設定變更為:

    <AssignMessage name="AM-GetSecret"> <AssignVariable> <Name>private.secretkey</Name> <Ref>propertyset.oauth.secret</Ref> </AssignVariable> <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables> </AssignMessage>

    「AssignVariable」設定會將「propertyset.oauth.secret」變數複製到「private.secretkey」變數。

    如果無法解析變數「propertyset.oauth.secret」,AssignMessage 政策就會因為「IgnoreUnresolvedVariables」這項設定而拋出錯誤訊息。

新增 OAuthV2 政策來驗證權杖

  1. 在 Proxy 的「Navigator」選單中,依序前往「Proxy endpoints」>「default」,然後點選下方的「PreFlow」

    「OAuthV2」政策應在「AssignMessage」政策之後執行。

  2. 在「Flow」窗格的要求流程中,點選「PreFlow」右側的「+」按鈕

  3. 選取「Create new policy」,在「Select Policy」下拉式選單的「Security」部分選取「OAuth v2.0」,然後將「Display Name」和「Name」設為 OA-VerifyToken

  4. 點選「Add」,然後在「Navigator」選單中的「Policies」下方,按一下「OA-VerifyToken」

    「Code」窗格會顯示「OAuthV2」政策設定。

  5. OAuthV2 政策設定變更為:

    <OAuthV2 name="OA-VerifyToken"> <Operation>VerifyJWTAccessToken</Operation> <Algorithm>HS256</Algorithm> <SecretKey> <Value ref="private.secretkey"/> </SecretKey> </OAuthV2>

    這項設定會指定 JWT 存取權杖使用 HS256 (HMAC-SHA256) 演算法,並將「AssignMessage」政策中建立的私有變數做為密鑰。

  6. 點選「Save」

點選「Check my progress」,確認目標已達成。 新增政策來驗證權杖

工作 3:新增政策來產生權杖

您還可以在 API Proxy 另外新增 Proxy 端點來建立 JWT 權杖。

新增權杖作業所需的 Proxy 端點

在正式環境,通常會另外建立 Proxy 來產生權杖。不過在本實驗室,您將透過同個 API Proxy 內的不同 Proxy 端點,建立權杖產生流程。

  1. 在 Proxy 的「Navigator」選單中,點選「Proxy endpoints」列的「+」按鈕。

    注意: 請勿點選「default」旁的「+」按鈕。

    這樣就能新增建立 JWT 所需的 Proxy 端點。

  2. 將「Name」指定為 token,然後點選「Add」

    「Code」窗格會顯示新 Proxy 端點「token」

  3. 變更整個「token」流程設定。從下列程式碼:

    <ProxyEndpoint name="token"> . . . </ProxyEndpoint>

    改為下列程式碼:

    <ProxyEndpoint name="token"> <PreFlow name="PreFlow"> <Request/> <Response/> </PreFlow> <PostFlow name="PostFlow"> <Request/> <Response/> </PostFlow> <Flows/> <HTTPProxyConnection> <BasePath>/token</BasePath> </HTTPProxyConnection> <RouteRule name="noTarget"/> </ProxyEndpoint>
  4. 點選「Save」

    更新這項設定後,會導致 2 項具體變更:

    • 「BasePath」設為 /token,這是將用來建立權杖的基本路徑。
    • 「RouteRule」不再參照目標端點。API Proxy 不須呼叫後端服務,即可建立權杖。

建立產生權杖的流程

  1. 依序前往 Proxy >「Proxy Endpoints」>「token」,然後在「Flow」點選「/token」右側的「+」

  2. 指定下列值來建立新的條件式流程:

    屬性
    流程名稱 generateToken
    條件類型 選取「Custom」
  3. 將「Condition」指定為下列值:

    (proxy.pathsuffix MatchesPath "/") and (request.verb = "POST") and (request.formparam.grant_type = "client_credentials")

    系統只會允許有效的用戶端憑證權杖要求。

  4. 點選「Add」。

附加 AssignMessage 政策來擷取屬性集的值

要產生權杖的政策「OAuthV2」也需存取 private.secretkey 變數。

  1. 在 Proxy 的「Navigator」選單中,依序前往「Proxy endpoints」>「token」,然後點選下方的「generateToken」

  2. 在「Flow」窗格中的要求流程,點選「generateToken」右側的「+」按鈕

  3. 在「Select Policy」中,選取「Select Existing policy」,然後點選「AM-GetSecret」

  4. 點選「Add」。

    同樣將「AssignMessage」政策附加到權杖 Proxy 端點 PreFlow。

新增 OAuthV2 政策來產生權杖

  1. 在 Proxy 的「Navigator」選單中,依序前往「Proxy endpoints」>「token」,然後點選下方的「generateToken」

  2. 在「Flow」窗格中的要求流程,點選「generateToken」右側的「+」按鈕

  3. 在「Select Policy」中,選取「Create new policy」,然後從「Security」選取「OAuth v2.0」,並將「Display Name」和「Name」設為 OA-GenerateToken

  4. 點選「Add」,然後在「Policies」中按一下「OA-GenerateToken」

    「Code」窗格會顯示「OAuthV2」政策設定。

  5. OAuthV2 政策設定變更為:

    <OAuthV2 name="OA-GenerateToken"> <Operation>GenerateJWTAccessToken</Operation> <Algorithm>HS256</Algorithm> <SecretKey> <Value ref="private.secretkey"/> </SecretKey> <SupportedGrantTypes> <!-- pass client_id and client_secret via basic auth header --> <GrantType>client_credentials</GrantType> </SupportedGrantTypes> <!-- 1800000 ms = 1800 s = 30 min --> <ExpiresIn>1800000</ExpiresIn> <GenerateResponse enabled="true"/> <RFCCompliantRequestResponse>true</RFCCompliantRequestResponse> </OAuthV2>

    這項設定會建立 JWT OAuth 權杖,效期為 30 分鐘。

對無效權杖要求拋出錯誤訊息

  1. 依序前往 Proxy >「Proxy Endpoints」>「token」,然後在「Flow」點選「/token」右側的「+」

  2. 指定下列值來建立新的條件式流程:

    屬性
    流程名稱 invalidRequest
    條件類型 選取「Custom」
    條件 DELETETHIS

    新增流程後,系統會刪除條件,因為無效的 generateToken 要求一律會經過這個流程。

  3. 點選「Add」。

  4. invalidRequest 流程中移除下列程式碼:

    <Condition>DELETETHIS</Condition>
  5. 在 Proxy 的「Navigator」選單中,依序前往「Proxy endpoints」>「token」,然後點選下方的「invalidRequest」

  6. 在「Flow」窗格中的要求流程,點選「invalidRequest」右側的「+」按鈕

  7. 選取「Create new policy」,然後從「Mediation」選取「Raise Fault」,並將「Display Name」和「Name」設為 RF-InvalidTokenRequest

  8. 點選「Add」,然後在「Policies」中按一下「RF-InvalidTokenRequest」

    「Code」窗格會顯示「RaiseFault」政策設定。

  9. RaiseFault 政策設定變更為:

    <RaiseFault name="RF-InvalidTokenRequest"> <FaultResponse> <Set> <StatusCode>400</StatusCode> <ReasonPhrase>Bad Request</ReasonPhrase> <Payload contentType="application/json">{ "error":"Bad request: use POST /token" }</Payload> </Set> </FaultResponse> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> </RaiseFault>

    如果要求無效,就會建立「400 Bad Request」回應。

  10. 點選「Save」

點選「Check my progress」,確認目標已達成。 新增政策來產生權杖

工作 4:部署 OAuth Proxy

在這項工作中,您會部署 API Proxy,並確認須有 OAuth 權杖才具備存取權。

確認執行階段執行個體是否可用

  1. 在 Cloud Shell 貼上並執行下列指令:

    export INSTANCE_NAME=eval-instance; export ENV_NAME=eval; export PREV_INSTANCE_STATE=; echo "waiting for runtime instance ${INSTANCE_NAME} to be active"; while : ; do export INSTANCE_STATE=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${GOOGLE_CLOUD_PROJECT}/instances/${INSTANCE_NAME}" | jq "select(.state != null) | .state" --raw-output); [[ "${INSTANCE_STATE}" == "${PREV_INSTANCE_STATE}" ]] || (echo; echo "INSTANCE_STATE=${INSTANCE_STATE}"); export PREV_INSTANCE_STATE=${INSTANCE_STATE}; [[ "${INSTANCE_STATE}" != "ACTIVE" ]] || break; echo -n "."; sleep 5; done; echo; echo "instance created, waiting for environment ${ENV_NAME} to be attached to instance"; while : ; do export ATTACHMENT_DONE=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${GOOGLE_CLOUD_PROJECT}/instances/${INSTANCE_NAME}/attachments" | jq "select(.attachments != null) | .attachments[] | select(.environment == \"${ENV_NAME}\") | .environment" --join-output); [[ "${ATTACHMENT_DONE}" != "${ENV_NAME}" ]] || break; echo -n "."; sleep 5; done; echo "***ORG IS READY TO USE***";

    這組指令會使用 Apigee API,判斷是否已建立 Apigee 執行階段執行個體,以及是否已附加 eval 環境

  2. 等待執行個體準備就緒。

    畫面上顯示 ***ORG IS READY TO USE*** 文字時,表示執行個體已準備就緒。Apigee 組織 (簡稱「組織」) 或許在實驗室啟動前就已建立,您可能不必等待這個執行個體建立完畢。

    等待組織準備就緒期間,歡迎進一步瞭解 OAuthSpikeArrest 政策遮蓋及隱藏資料,以及不透明權杖和 JWT

部署 API Proxy

  1. 前往 Cloud 控制台的 Apigee

  2. 在左側導覽選單中,依序選取「Proxy 開發」>「API Proxy」,然後點選「bank-v1」

  3. 點選「Develop」分頁標籤。

  4. 點選「Deploy」,然後「Environment」請選取「eval」。

    畫面上會顯示對話方塊,請您確認部署作業。

  5. 在「Service Account」指定服務帳戶的電子郵件地址:

    apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
  6. 依序點選「Deploy」>「Confirm」

  7. 點選「Overview」分頁標籤,等待「eval」部署狀態顯示 Proxy 部署完畢。

點選「Check my progress」,確認目標已達成。 部署 API Proxy

測試 API Proxy

您可以使用主機名稱「eval.example.com」呼叫 Apigee 組織中的 eval 環境。這個主機名稱的 DNS 項目已在專案中建立,會解析為 Apigee 執行階段執行個體的 IP 位址。此外,這個 DNS 項目是在私人可用區中建立,只會顯示於內部網路。

Cloud Shell 不在內部網路中,無法使用 Cloud Shell 指令解析這個 DNS 項目。貴組織內的虛擬機器 (VM) 可存取私人可用區 DNS。系統已自動建立虛擬機器 apigeex-test-vm,可用來呼叫 API Proxy。

  1. 在 Cloud Shell 啟用連往測試 VM 的 SSH 連線:

    TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)") gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite

    如果系統要求您授權,請點選「授權」

  2. 對於 Cloud Shell 中顯示的每個問題,按下 EnterReturn 鍵使用預設輸入內容。

    您是以專案擁有者的身分登入,因此能透過 SSH 連至這個機器。

    Cloud Shell 工作階段現在會在 VM 內執行。

  3. eval 環境呼叫部署的 bank-v1 API Proxy:

    curl -i -k -X GET "https://eval.example.com/bank/v1/customers"

    -k 選項會告知 curl 略過 TLS 憑證驗證。在本實驗室中,Apigee 執行階段使用的憑證為自行簽署,而不是由信任的憑證授權單位 (CA) 建立。

    注意: 在正式環境中,切勿使用 -k 選項略過憑證驗證。

    這個 API 會嘗試擷取客戶名單。現在您應該會看到「401 Unauthorized」回應,大致如下:

    HTTP/2 401 content-type: application/json www-authenticate: Bearer realm="null",error="invalid_token",error_description="oauth.v2.InvalidAccessToken: Invalid access token" x-request-id: 99263881-d0f7-4495-b886-0253f28a2e05 content-length: 101 date: Tue, 11 Jan 2022 18:59:01 GMT via: 1.1 google {"fault":{"faultstring":"Invalid access token","detail":{"errorcode":"oauth.v2.InvalidAccessToken"}}}

    這項回應指出,由於未提供存取權杖,API Proxy 已禁止存取後端服務。

  4. 輸入 exit 指令,離開 SSH 工作階段並返回 Cloud Shell。

工作 5:新增 API 產品、開發人員和應用程式

在這項工作中,您會新增 API 產品來提供 API 存取權。此外,您也將建立開發人員,以及與 API 產品相關聯的應用程式。

建立 API 產品

  1. 前往 Cloud 控制台的 Apigee

  2. 在左側導覽選單中,依序選取「分配」>「API 產品」

  3. 點選「+Create」來建立新的 API 產品。

  4. 在「Product details」窗格中,指定下列項目:

    屬性
    名稱 bank-readonly
    顯示名稱 bank (read access)
    環境 選取「eval」
    存取權 選取「Public」

    維持選取「Automatically approve access requests」

  5. 在「Operations」部分,點選「+Add an Operation」

    作業是用於指定與 API 產品相關聯的應用程式,可以在哪些 API Proxy 中發出哪些要求。

    注意: 確認按鈕位於「Operations」部分,而非「GraphQL Operations」。
  6. 指定下列項目:

    屬性
    API Proxy 選取「bank-v1 API Proxy」
    路徑 /**
    方法 選取「GET」

    路徑運算式 /\*\* 表示允許任何符合基本路徑的要求。

    在正式環境中,您可能會逐一新增允許的作業,而不是使用這個萬用字元路徑運算式。

  7. 點選「Save」來儲存作業。

  8. 點選「Products Detail」頁面上方的「Save」,儲存 API 產品。

  9. 返回「分配」>「API 產品」頁面。

    畫面上會列出 API 產品。

建立應用程式開發人員

建立應用程式之前,必須先建立應用程式開發人員。

  1. 在左側導覽選單中,依序點選「分配」>「開發人員」

  2. 點選「+Create」,建立新的應用程式開發人員。

  3. 指定下列項目:

    屬性
    名字 Joe
    姓氏 Developer
    使用者名稱 joe
    電子郵件 joe@example.com
  4. 點選「Add」來建立應用程式開發人員。

建立具有 bank-v1 存取權的應用程式

  1. 在左側導覽選單中,依序點選「分配」>「應用程式」

  2. 點選「+Create」來建立新的應用程式。

  3. 在「App details」窗格中,指定下列項目:

    屬性
    名稱 readonly-app
    開發人員 選取「joe@example.com」
  4. 在「Credentials」窗格中,依序點選「Add credentials」>「Add products」,從下拉式選單中選取「bank (read access)」,然後點選「Add」來新增產品。

  5. 點選右上角的「Create」來建立應用程式。

    應用程式的「Key」和「Secret」已設定完成。

  6. 點選「Key」和「Secret」旁的「Show」圖示。

    由於須有 OAuth 存取權杖才能存取這個 API,應用程式會使用金鑰和密鑰做為憑證,藉此建立 OAuth 存取權杖。

點選「Check my progress」,確認目標已達成。 新增 API 產品並建立應用程式

測試 API

  1. 在 Cloud Shell 啟用連往測試 VM 的 SSH 連線:

    TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)") gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite

    如果系統要求您授權,請點選「授權」

    Cloud Shell 工作階段現在會在 VM 內執行。

  2. 執行下列指令,取得應用程式的用戶端金鑰和密鑰:

    export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null); echo "PROJECT_ID=${PROJECT_ID}" export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output); echo "CONSUMER_KEY=${CONSUMER_KEY}" export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output); echo "CONSUMER_SECRET=${CONSUMER_SECRET}"

    第一組指令會讀取 gcloud 設定來取得目前的專案,第二和第三組指令則會使用 Apigee API 擷取用戶端金鑰和密鑰。您傳送的存取權杖具有登入使用者的權限,因此要求已獲得授權。

    由於使用的是 OAuth 用戶端憑證授權類型,用戶端應用程式必須在 Authorization 標頭中傳送用戶端金鑰和密鑰,才能產生存取權杖。

  3. 執行下列指令來產生 JWT 存取權杖:

    export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials"); echo ${TOKEN_RESPONSE} export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output); echo "JWT_TOKEN=${JWT_TOKEN}"

    第一組指令會呼叫權杖端點並儲存回應。系統隨後會從 JSON 回應中擷取權杖,並儲存在「JWT_TOKEN」

  4. 執行下列指令,使用 JWT 權杖測試要求:

    curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/customers"

    API 呼叫應會傳回客戶名單。

    注意: 如果收到的回應為「Your client does not have permission to the requested URL」,請確認您在工作 1 中設定的目標對象正確無誤。
  5. 輸入 exit 指令,離開 SSH 工作階段並返回 Cloud Shell。

工作 6:新增頻率限制

在這項工作中,您會新增 SpikeArrest 政策,根據 API 產品配額設定限制 API 呼叫頻率。

「SpikeArrest」政策可用來指定允許的流量頻率上限,防止 API 和後端流量暴增,確保後端不會因流量大到無法處理而癱瘓。

對權杖產生作業新增 SpikeArrest 政策

SpikeArrest 政策會對呼叫「/token」API 的流量設下整體頻率限制。

  1. 前往 Cloud 控制台的 Apigee

  2. 在左側導覽選單中,依序選取「Proxy 開發」>「API Proxy」,然後點選「bank-v1」

  3. 點選「Develop」分頁標籤。

  4. 在 Proxy 的「Navigator」選單中,依序前往「Proxy endpoints」>「token」,然後點選下方的「PreFlow」

    「SpikeArrest」政策應在條件式流程政策之前執行。

  5. 在「Flow」窗格的要求流程中,點選「PreFlow」右側的「+」按鈕

  6. 選取「Create new policy」,然後從「Traffic Management」選取「Spike Arrest」,並將「Display Name」和「Name」設為 SA-LimitTokenRate

  7. 點選「Add」,然後在「Policies」中按一下「SA-LimitTokenRate」

    「Code」窗格會顯示「SpikeArrest」政策設定。

  8. SpikeArrest 政策設定變更為:

    <SpikeArrest name="SA-LimitTokenRate"> <Rate>5pm</Rate> <UseEffectiveCount>false</UseEffectiveCount> </SpikeArrest>

    這項設定會將允許的要求頻率上限指定為「每分鐘 5 個」。所有流量都會受這項「SpikeArrest」政策限制。

    注意: 本實驗室將 SpikeArrest 限制設為每分鐘 5 個要求,是為了方便測試。這項限制在實際情況下通常過低。

    將「UseEffectiveCount」設為 false,即可指定 SpikeArrest 政策使用權杖 bucket 演算法。政策會將頻率劃分為較小的時間間隔,以確保流量平穩。每分鐘 5 個要求,表示每 1/5 分鐘或每 12 秒處理 1 個要求。如果訊息處理器先後接收兩個要求的時間間隔不到 12 秒,可能會拒絕後者。

對 API 要求新增 SpikeArrest 政策

SpikeArrest 政策會對呼叫「/bank/v1」API 的流量設下頻率限制,並套用於每個應用程式。

  1. 在 Proxy 的「Navigator」選單中,依序前往「Proxy endpoints」>「default」,然後點選下方的「PreFlow」

    「SpikeArrest」政策須在呼叫一開始,以及 OAuthV2 VerifyJWTAccessToken 政策之後執行,才能依應用程式限制頻率。

  2. 在「Flow」窗格的要求流程中,點選「PreFlow」右側的「+」按鈕

  3. 選取「Create new policy」,然後從「Traffic Management」選取「Spike Arrest」,並將「Display Name」和「Name」設為 SA-LimitRateByApp

  4. 點選「Add」,然後在「Policies」中按一下「SA-LimitRateByApp」

    「Code」窗格會顯示「SpikeArrest」政策設定。

  5. SpikeArrest 政策設定變更為:

    <SpikeArrest name="SA-LimitRateByApp"> <Rate>5pm</Rate> <Identifier ref="client_id" /> <UseEffectiveCount>true</UseEffectiveCount> </SpikeArrest>

    與先前的政策相同,這項設定會將允許的要求頻率上限指定為「每分鐘 5 個」。不過這項政策指定了「Identifier」,可分別維持各個「client_id」的 SpikeArrest 頻率。用戶端 ID 會透過「OA-VerifyToken」政策填入,每個開發人員應用程式都有專屬的用戶端 ID。

    當「UseEffectiveCount」設為 true,即可指定系統持續計算區域內所有流量的頻率。系統將按照政策維護計數器,計算每個週期收到的要求。如果是計算「每分鐘」要求數,則時間間隔為一分鐘。要求數會根據滑動區間算出。

    滑動區間範例,要求數為 48 和 5。

    以上範例假設頻率為每分鐘 50 個要求,因此計數器以一分鐘為間隔;如果指定計算每秒要求數,則計數器會以一秒為間隔。現在假設這一分鐘已經過 10 秒,如箭頭所示。前一分鐘有 48 個要求,這一分鐘到第 10 秒為止有 5 個要求。

    如果要允許其他要求,頻率必須低於每分鐘 50 個的限制,計算出的頻率為:

    request_rate = (48 * (60-10)/60) + 6 = 46

    由於在目前週期,僅經過 60 秒中的 10 秒,剩餘 50 秒會依前一個週期的要求數計算,也就是 48 的 5/6,等於 40。如果允許 1 個要求,則目前週期的要求數將為 5 + 1,也就是 6。最終系統計算到的要求數為 46 個,低於每分鐘 50 個的限制,因此該要求獲准。

  6. 依序點選「Save」>「Save as new revision」

  7. 點選「Deploy」,然後「Environment」請選取「eval」

  8. 在「Service Account」指定服務帳戶的電子郵件地址:

apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
  1. 依序點選「Deploy」>「Confirm」
  2. 點選「Overview」分頁標籤,等待「eval」部署狀態顯示 Proxy 部署完畢。

點選「Check my progress」,確認目標已達成。 新增 SpikeArrest 政策

測試頻率限制

  1. 在 Cloud Shell 啟用連往測試 VM 的 SSH 連線:

    TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)") gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite

    如果系統要求您授權,請點選「授權」

    Cloud Shell 工作階段現在會在 VM 內執行。

  2. 執行下列指令,取得應用程式的用戶端金鑰和密鑰:

    export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null); echo "PROJECT_ID=${PROJECT_ID}" export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output); echo "CONSUMER_KEY=${CONSUMER_KEY}" export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output); echo "CONSUMER_SECRET=${CONSUMER_SECRET}"
  3. 重複執行下列指令,即可產生多個存取權杖:

    curl -i -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials"

    您應該很快就會收到「429 Too Many Requests」回應,表示已超出頻率限制。由於這項政策的「UseEffectiveCount」為 false,系統會使用「權杖 bucket」演算法來穩定處理流量。您可能會在傳送第 5 個要求前收到通知,指出您違反尖峰流量限制。

  4. 執行下列指令來儲存 JWT 存取權杖:

    export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials"); echo ${TOKEN_RESPONSE} export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output); echo "JWT_TOKEN=${JWT_TOKEN}"
  5. 重複傳送下列指令來測試 API 呼叫的 SpikeArrest 政策:

    curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/customers"

    由於「UseEffectiveCount」為 true,這項政策會使用滑動區間演算法。遭到封鎖前,您應該可以成功提出 5 次要求。

  6. 輸入 exit 指令,離開 SSH 工作階段並返回 Cloud Shell。

工作 7:資料遮蓋

在這項工作中,您會建立資料遮罩,在偵錯工作階段隱藏特定欄位。

啟動偵錯工作階段

偵錯工具可監控在 Apigee 上執行的 API Proxy,並排解相關問題,還能在 API 呼叫期間,幫助您檢查每個步驟的詳細資料。

  1. 在左側導覽選單中,依序選取「Proxy 開發」>「API Proxy」,然後點選「bank-v1」

  2. 點選「Debug」分頁標籤。

  3. 在「Start debug session」窗格中點選「Start debug session」,然後從環境下拉式選單中選取「eval」環境。

  4. 點選「Start」

    偵錯工作階段可能需要一小段時間,才會開始擷取要求。

    注意: 如果畫面頂端出現以紅色方塊標示錯誤訊息「Error fetching debug transactions」或「List debug session transaction error」,偵錯工作階段可能仍會正常運作。

    請傳送 API 要求,然後檢查偵錯工作階段。

偵錯要求

  1. 在 Cloud Shell 啟用連往測試 VM 的 SSH 連線:

    TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)") gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite

    如果系統要求您授權,請點選「授權」

    Cloud Shell 工作階段現在會在 VM 內執行。

  2. 執行下列指令來取得應用程式權杖:

    export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null); echo "PROJECT_ID=${PROJECT_ID}" export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output); echo "CONSUMER_KEY=${CONSUMER_KEY}" export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output); echo "CONSUMER_SECRET=${CONSUMER_SECRET}" export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials"); echo ${TOKEN_RESPONSE} export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output); echo "JWT_TOKEN=${JWT_TOKEN}"
  3. 對 API 傳送下列要求:

    curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/customers/abe@example.org/accounts"
  4. 返回 Apigee UI 頁面。

    「Debug」頁面應會顯示 2 個要求:POST (產生權杖) 和 GET (擷取使用者帳戶)。

  5. 點選「GET」要求。

    GET 要求詳細資料會隨即顯示。

  6. 點選第一個「AM-GetSecret」政策,將「propertyset.oauth.secret」變數複製到「private.secretkey」變數。

    Apigee UI 頁面,其中有醒目顯示的「AssignMessage」圖示和「Variables Read」說明。

    「Phase Details」不會顯示私有變數,因為前置字元為「private.」的變數會從偵錯工作階段中隱藏。不過,由於屬性集變數仍保有相同的機密資料,建議還是對偵錯流量的使用者隱藏這些資料。

  7. 點選來自後端的回應,也就是工廠圖示左側的圓圈。

    「Transaction Map」類別中醒目顯示的後端切換鈕,以及「Response Content」中醒目顯示的內文。

    回應包含使用者的帳戶和帳戶餘額。

建立偵錯遮罩

  1. 在相同瀏覽器視窗中開啟新分頁,然後前往 Apigee API 參考資料

    Apigee API 參考資料提供各種 API 呼叫的詳細資料,可用來管理 Apigee,以及呼叫 Apigee API。這個頁面會顯示「organization.environments」API 呼叫。

  2. 捲動到頁面底部,然後點選「updateDebugmask」

    這個 API 呼叫會更新環境的偵錯遮罩。

  3. 在「Try this API」窗格中的「name」要求參數部分,輸入下列程式碼:

    organizations/{{{ project_0.project_id | PROJECT }}}/environments/eval/debugmask
  4. 在「request body」部分,輸入下列程式碼:

    { "responseJSONPaths": [ "$[*].balance" ], "variables": [ "propertyset.oauth.secret" ] }

    這個酬載將遮蓋「propertyset.oauth.secret」變數,以及回應酬載物件陣列中的各個「balance」欄位

  5. 點選「Execute」

    如果畫面顯示彈出式方塊並要求您選擇帳戶,請選取學生帳戶。

  6. 點選「Allow」,允許頁面使用學生憑證。

測試偵錯遮罩

  1. 在 Apigee UI 的左側導覽選單中,依序選取「Proxy 開發」>「API Proxy」,然後點選「bank-v1」

  2. 點選「Debug」分頁標籤。

  3. 在「Start debug session」窗格的環境下拉式選單中,選取「eval」

  4. 點選「Start」

  5. 如果 SSH 連線已關閉,請在 Cloud Shell 啟用連往測試 VM 的 SSH 連線:

    TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)") gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
  6. 取得權杖,然後再次傳送 API 要求:

    export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null) export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output) export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output) export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials") export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output) curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/customers/abe@example.org/accounts"
  7. 返回 Apigee UI 的「偵錯」頁面,然後點選「GET」要求。

  8. 點選「AM-GetSecret」政策。

    「propertyset.oauth.secret」變數會遭到遮蓋。

    隱藏模式下的 propertyset.oauth.secret 變數。

  9. 點選後端回應的「Proxy Response Flow Started」

    每個「balance」欄位都遭到遮蓋。

    內文中的「balance」欄位都已隱藏。

工作 8:處理錯誤

在這項工作中,您會建立預設條件式流程來限制呼叫特定後端資源,並重新編寫後端錯誤訊息。

測試 API

  1. 如果 SSH 連線已關閉,請在 Cloud Shell 啟用連往測試 VM 的 SSH 連線:

    TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)") gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
  2. 輸入「Y」即可繼續,然後按兩次 ENTER 鍵,將通關密語留空。

  3. 取得權杖,並「/users」傳送 GET 要求:

    export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null) export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output) export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output) export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials") export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output) curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/users"

    後端服務無法識別「GET /users」要求,因此會傳回 404 回應,大致如下:

    HTTP/2 404 x-powered-by: Express content-security-policy: default-src 'none' x-content-type-options: nosniff content-type: text/html; charset=utf-8 x-cloud-trace-context: 7e96528757cc5053ba4fc8853037b02d;o=1 date: Wed, 19 Jan 2022 01:49:53 GMT server: Google Frontend content-length: 144 x-request-id: 2d8c8002-3152-4fc2-a60b-1729dd5483d8 via: 1.1 google <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /users</pre> </body> </html>

    回應傳回的 HTML 酬載格式與「RF-InvalidTokenRequest」酬載不符。此外,後端回應可能含有機密資料,因此建議您重新編寫後端服務的錯誤回應。

重新編寫「404 Not Found」錯誤訊息

錯誤規則可用來偵測錯誤及重新編寫錯誤訊息。

您將使用「RaiseFault」政策設定新回應。

  1. 前往 Cloud 控制台的 Apigee

  2. 在左側導覽選單中,依序選取「Proxy 開發」>「API Proxy」,然後點選「bank-v1」

  3. 點選「Develop」分頁標籤。

  4. 在 Proxy 的「Navigator」選單中,點選「Policies」旁的「+」

  5. 從「Mediation」選取「Raise Fault」,然後將「Display Name」和「Name」設為 RF-404NotFound

  6. 點選「Create」。在「Policies」點選「RF-404NotFound」

  7. RaiseFault 政策設定變更為:

    <RaiseFault name="RF-404NotFound"> <FaultResponse> <Remove> <Headers/> </Remove> <Set> <StatusCode>404</StatusCode> <ReasonPhrase>Not Found</ReasonPhrase> <Headers> <Header name="FaultName">{fault.name}</Header> </Headers> <Payload contentType="application/json">{ "error": "{request.verb} {proxy.pathsuffix} not found" }</Payload> </Set> </FaultResponse> <AssignTo createNew="true" type="response"/> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> </RaiseFault>

    「Remove」區段會先移除可能來自後端服務的所有標頭,然後「Set」區段會建立回應。「FaultName」標頭已新增,會在拋出錯誤訊息時顯示「fault.name」變數的值。fault.name 變數會指定錯誤名稱。

建立 FaultRule

  1. 在 Proxy 的「Navigator」選單中,點選「Target endpoints」中的「default」

    「預設目標端點」包含傳回 404 回應的後端目標呼叫。系統會將 404 視為失敗代碼,在端點拋出錯誤訊息,並使用目標端點中指定的「FaultRules」,重新編寫 API 回應。

  2. 前往「TargetEndpoint」設定,然後直接在 TargetEndpoint 標記下方新增下列「FaultRules」區段:

    <FaultRules> <FaultRule name="404"> <Step> <Name>RF-404NotFound</Name> </Step> <Condition>response.status.code == 404</Condition> </FaultRule> </FaultRules>

    現在 TargetEndpoint 的開頭大致如下:

    <TargetEndpoint name="default"> <FaultRules> <FaultRule name="404"> <Step> <Name>RF-404NotFound</Name> </Step> <Condition>response.status.code == 404</Condition> </FaultRule> </FaultRules>
  3. 依序點選「Save」>「Save as new revision」

  4. 點選「Deploy」,然後「Environment」請選取「eval」

  5. 在「Service Account」指定服務帳戶的電子郵件地址:

    apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
  6. 依序點選「Deploy」>「Confirm」

  7. 點選「Overview」分頁標籤,等待「eval」部署狀態顯示 Proxy 部署完畢。

測試端點回應錯誤

  1. 如果 SSH 連線已關閉,請在 Cloud Shell 啟用連往測試 VM 的 SSH 連線:

    TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)") gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
  2. 取得權杖,並「/users」傳送 GET 要求:

    export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null) export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output) export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output) export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials") export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output) curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/users"

    重新編寫後的回應大致如下:

    HTTP/2 404 faultname: ErrorResponseCode content-type: application/json x-request-id: 8d9db301-b3c7-4957-816d-93e796306dfb content-length: 39 date: Tue, 18 Jan 2022 06:42:23 GMT via: 1.1 google { "error": "GET /users not found" }

    現在回應會使用 JSON。請注意,「faultname」標頭的值「ErrorResponseCode」,是目標傳回失敗代碼時指定的「fault.name」變數值。後端服務傳回 404 回應後,系統隨即會拋出錯誤訊息並評估目標端點錯誤規則。404 錯誤規則隨後會重新編寫回應。

新增 404 條件式流程

只要在 Proxy 端點條件式流程結尾加入一個條件式流程,就能在系統傳送非預期的要求,且其他條件式流程都不符合條件時,拋出錯誤訊息,不必透過後端回應,這種模式可確保只有條件式流程列出的作業會傳遞至後端,且能讓您只允許存取部分後端服務資源。

  1. 在 Proxy 的「Navigator」選單中,依序前往「Proxy Endpoints」>「default」,然後在「flow」點選 /bank/v1 旁的「+」

  2. 指定下列值來建立新的條件式流程:

    屬性
    流程名稱 404NotFound
    條件類型 選取「Custom」
    條件 DELETETHIS
  3. 點選「Add」。

  4. 404NotFound 流程中移除下列程式碼:

    <Condition>DELETETHIS</Condition>

    如果先前所有條件式流程的條件都不相符,就會執行「404NotFound」流程。

  5. 在 Proxy 的「Navigator」選單中,依序前往「Proxy endpoints」>「default」,然後點選下方的「404NotFound」

  6. 在「Flow」窗格中,點選「404NotFound」要求流程右側的「+」按鈕

  7. 在「Select Policy」中,選取「Select Existing policy」,然後點選「RF-404NotFound」

  8. 點選「Add」。

  9. 依序點選「Save」>「Save as new revision」

  10. 點選「Deploy」,然後「Environment」請選取「eval」

  11. 在「Service Account」指定服務帳戶的電子郵件地址:

    apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
  12. 依序點選「Deploy」>「Confirm」

  13. 點選「Overview」分頁標籤,等待「eval」部署狀態顯示 Proxy 部署完畢。

點選「Check my progress」,確認目標已達成。 新增錯誤處理程序

測試 404 條件式流程

  1. 如果 SSH 連線已關閉,請在 Cloud Shell 啟用連往測試 VM 的 SSH 連線:

    TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)") gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
  2. 取得權杖,並「/users」傳送 GET 要求:

    export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null) export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output) export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output) export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials") export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output) curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/users"

    重新編寫後的回應大致如下:

    HTTP/2 404 faultname: RaiseFault content-type: application/json x-request-id: d6bbd48f-65bd-4551-9236-636fad03a609 content-length: 39 date: Tue, 18 Jan 2022 07:07:58 GMT via: 1.1 google alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 { "error": "GET /users not found" }

    現在「faultname」標頭的值為「RaiseFault」,也就是 RaiseFault 政策拋出錯誤訊息時使用的「fault.name」值。404NotFound 條件式流程中的 RaiseFault 政策確實產生回應。

恭喜!

在本實驗室中,您藉由要求具備 JWT OAuth 權杖,保護 API 安全。此外,您新增 SpikeArrest 政策來限制流量,以及使用私有變數和資料遮蓋功能,在偵錯工作階段中隱藏機密資料。您還重新編寫後端錯誤訊息,並使用 404 條件式流程,限制呼叫後端的特定資源。

後續步驟/瞭解詳情

使用手冊上次更新日期:2025 年 8 月 6 日

實驗室上次測試日期:2025 年 8 月 6 日

Copyright 2026 Google LLC 保留所有權利。Google 和 Google 標誌是 Google LLC 的商標,其他公司和產品名稱則有可能是其關聯公司的商標。

准备工作

  1. 实验会创建一个 Google Cloud 项目和一些资源,供您使用限定的一段时间
  2. 实验有时间限制,并且没有暂停功能。如果您中途结束实验,则必须重新开始。
  3. 在屏幕左上角,点击开始实验即可开始

使用无痕浏览模式

  1. 复制系统为实验提供的用户名密码
  2. 在无痕浏览模式下,点击打开控制台

登录控制台

  1. 使用您的实验凭证登录。使用其他凭证可能会导致错误或产生费用。
  2. 接受条款,并跳过恢复资源页面
  3. 除非您已完成此实验或想要重新开始,否则请勿点击结束实验,因为点击后系统会清除您的工作并移除该项目

此内容目前不可用

一旦可用,我们会通过电子邮件告知您

太好了!

一旦可用,我们会通过电子邮件告知您

一次一个实验

确认结束所有现有实验并开始此实验

使用无痕浏览模式运行实验

Using an Incognito or private browser window is the best way to run this lab. This prevents any conflicts between your personal account and the Student account, which may cause extra charges incurred to your personal account.