GSP844

概览
Apigee 是一个用于开发和管理 API 的平台。Apigee 可帮助您保障 API 的访问安全、限制对 API 的访问速率,还提供用于保障 API 数据内部访问安全的相关功能。
在本实验中,您将创建一个需要 OAuth 令牌才能访问的 API。您将通过 SpikeArrest 政策限制不同应用调用 API 的速率,并使用私有变量和数据遮盖功能,对调试 API 流量的用户隐藏敏感数据。
目标
在本实验中,您将学习如何执行以下任务:
- 通过要求提供 OAuth 令牌来保障 API 访问安全
- 通过 SpikeArrest 政策限制总体流量速率和不同应用的流量速率
- 在调试 API 调用时,使用私有变量和数据遮盖功能隐藏敏感数据
- 将对后端的调用限制在指定资源范围内
- 重写后端错误消息,以防数据泄露
设置和要求
点击“开始实验”按钮前的注意事项
请阅读以下说明。实验是计时的,并且您无法暂停实验。计时器在您点击开始实验后即开始计时,显示 Google Cloud 资源可供您使用多长时间。
此实操实验可让您在真实的云环境中开展实验活动,免受模拟或演示环境的局限。为此,我们会向您提供新的临时凭据,您可以在该实验的规定时间内通过此凭据登录和访问 Google Cloud。
为完成此实验,您需要:
- 能够使用标准的互联网浏览器(建议使用 Chrome 浏览器)。
注意:请使用无痕模式(推荐)或无痕浏览器窗口运行此实验。这可以避免您的个人账号与学生账号之间发生冲突,这种冲突可能导致您的个人账号产生额外费用。
注意:请仅使用学生账号完成本实验。如果您使用其他 Google Cloud 账号,则可能会向该账号收取费用。
注意:建议您使用新的无痕式窗口完成本实验。
如何开始实验并登录 Google Cloud 控制台
-
点击开始实验按钮。如果该实验需要付费,系统会打开一个对话框供您选择支付方式。左侧是“实验详细信息”窗格,其中包含以下各项:
- “打开 Google Cloud 控制台”按钮
- 剩余时间
- 进行该实验时必须使用的临时凭据
- 帮助您逐步完成本实验所需的其他信息(如果需要)
-
点击打开 Google Cloud 控制台(如果您使用的是 Chrome 浏览器,请右键点击并选择在无痕式窗口中打开链接)。
该实验会启动资源并打开另一个标签页,显示“登录”页面。
提示:将这些标签页安排在不同的窗口中,并排显示。
注意:如果您看见选择账号对话框,请点击使用其他账号。
-
如有必要,请复制下方的用户名,然后将其粘贴到登录对话框中。
{{{user_0.username | "<用户名>"}}}
您也可以在“实验详细信息”窗格中找到“用户名”。
-
点击下一步。
-
复制下面的密码,然后将其粘贴到欢迎对话框中。
{{{user_0.password | "<密码>"}}}
您也可以在“实验详细信息”窗格中找到“密码”。
-
点击下一步。
重要提示:您必须使用实验提供的凭据。请勿使用您的 Google Cloud 账号凭据。
注意:在本实验中使用您自己的 Google Cloud 账号可能会产生额外费用。
-
继续在后续页面中点击以完成相应操作:
- 接受条款及条件。
- 由于这是临时账号,请勿添加账号恢复选项或双重验证。
- 请勿注册免费试用。
片刻之后,系统会在此标签页中打开 Google Cloud 控制台。
注意:如需访问 Google Cloud 产品和服务,请点击导航菜单,或在搜索字段中输入服务或产品的名称。
激活 Cloud Shell
Cloud Shell 是一种装有开发者工具的虚拟机。它提供了一个永久性的 5GB 主目录,并且在 Google Cloud 上运行。Cloud Shell 提供可用于访问您的 Google Cloud 资源的命令行工具。
-
点击 Google Cloud 控制台顶部的激活 Cloud Shell
。
-
在弹出的窗口中执行以下操作:
- 继续完成 Cloud Shell 信息窗口中的设置。
- 授权 Cloud Shell 使用您的凭据进行 Google Cloud API 调用。
如果您连接成功,即表示您已通过身份验证,且项目 ID 会被设为您的 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 自动补全功能。
- (可选)您可以通过此命令列出活跃账号名称:
gcloud auth list
- 点击授权。
输出:
ACTIVE: *
ACCOUNT: {{{user_0.username | "ACCOUNT"}}}
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- (可选)您可以通过此命令列出项目 ID:
gcloud config list project
输出:
[core]
project = {{{project_0.project_id | "PROJECT_ID"}}}
注意:如需查看在 Google Cloud 中使用 gcloud 的完整文档,请参阅 gcloud CLI 概览指南。
打开 Apigee 控制台
如需打开 Apigee 控制台,请执行以下操作:
- 在 Google Cloud 控制台中,在搜索字段中输入
Apigee,然后点击搜索结果中的 Apigee API Management。
Apigee 控制台会随即打开,着陆页会显示指向常用位置的快捷链接。
- 在导航菜单 (
) 中,点击 Apigee 旁边的收藏 (
)。
Apigee 现在已作为收藏项添加到导航菜单中。
任务 1. 使用 Apigee API 代理来代理后端服务
在此任务中,您将创建一个 Apigee API 代理,此代理将作为后端服务的 Facade。API 代理将使用一个服务账号,以便向 Cloud Run 服务提供 OpenID Connect 身份令牌。
名为 simplebank-rest 的后端服务已创建完成并部署到 Cloud Run。同时也已为您创建好对应的服务账号。
创建 Apigee 代理
-
在 Cloud Shell 中,如需检索后端服务的网址,请使用以下命令:
gcloud run services describe simplebank-rest --platform managed --region {{{project_0.default_region |REGION}}} --format 'value(status.url)'
请保存此网址,在创建 API 代理时会用到它。
-
在 Cloud 控制台中前往 Apigee 界面。
-
在左侧导航菜单中,依次选择代理开发 > API 代理。
-
如需使用代理向导创建新代理,请点击 + 创建。
您将为后端服务创建反向代理。此 API 代理将使用 OpenAPI 规范来创建 API 框架。
-
对于代理模板框,在 OpenAPI 规范模板中选择反向代理(最常见)。
-
对于 OpenAPI 文件,请在浏览器中打开相应网址,系统会将 OpenAPI 规范 YAML 文件下载到您的计算机:
https://storage.googleapis.com/spls/gsp844/simplebank-backend.yaml
-
点击浏览,然后从计算机中选择 OpenAPI 文件,再点击下一步。
-
指定以下有关代理详情的内容:
| 属性 |
值 |
| 代理名称 |
bank-v1 |
| 基本路径 |
/bank/v1 |
| 描述 |
SimpleBank 只读 API |
| 目标(现有 API) |
后端网址
|
注意:请确认使用“/bank/v1”而非“/bank-v1”作为基本路径。
目标应为之前在该任务中检索到的后端网址,应如下所示:
https://simplebank-rest-nu7rb74j5a-uw.a.run.app
-
点击下一步。
-
将其他设置保留默认值,然后点击创建。
-
点击开发标签页。
注意:代理端点中已添加多个流,每个流都指定了 OpenAPI 规范中某项操作的谓词和路径条件。
修改目标以发送 OpenID Connect 身份令牌
该后端服务部署后要求通过身份验证才能访问,因此,如果没有有效的 OpenID Connect 身份令牌,您将无法调用该服务。
HTTPTargetConnection 指定服务的后端目标。
-
在代理的导航菜单中,点击目标端点部分中的 PreFlow。
-
找到以下代码(您的网址会有所不同):
<HTTPTargetConnection>
<URL>https://simplebank-rest-zce6j3rjwq-uw.a.run.app</URL>
</HTTPTargetConnection>
注意:如果您未看到 HTTPTargetConnection 部分,请确保您点击的是“目标端点”部分中的 PreFlow,而不是“代理端点”部分中的 PreFlow。
-
在网址下方添加如下所示的 Authentication 部分:
<Authentication>
<GoogleIDToken>
<Audience>AUDIENCE</Audience>
</GoogleIDToken>
</Authentication>
-
将 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>
-
点击保存。
点击“检查我的进度”以验证是否完成了以下目标:
创建 API 代理
任务 2. 向 API 代理添加 OAuth
在此任务中,您将向 API 代理添加 OAuthV2 政策。使用 VerifyJWTAccessToken 操作的 OAuthV2 政策会在运行时强制执行访问令牌验证,仅允许具有有效 OAuth 访问令牌的应用访问该 API。
OAuthV2 政策可以创建和验证不透明令牌及 JSON Web 令牌 (JWT)。此 API 代理将使用 JWT 作为访问令牌。
属性集将用于存储在创建和验证 JWT 时使用的签名密文。
在属性集中创建签名密文
JWT 将使用基于哈希的消息认证码 (HMAC) 进行签名。此类加密签名需要密文。
-
在代理的导航菜单中,点击资源旁边的 +。
-
在资源类型下拉菜单中,选择属性集。
-
指定 oauth.properties 作为资源名称,然后点击添加。
-
在 oauth.properties 代码窗格中,添加以下属性:
secret=thisisnotagoodsecret,useabettersecretinproduction
您可以使用流变量 propertyset.oauth.secret 在代码中访问该值。
注意:属性集值以明文形式存储。在生产环境中,您应将 HMAC 密文存储在加密位置,且务必使用更安全(随机生成)的密文。
添加 AssignMessage 政策以检索属性集值
必须以私有变量的形式向 OAuth 政策提供签名密文,但 propertyset.oauth.secret 变量并非私有变量。此 AssignMessage 政策将基于属性集变量创建一个私有变量。
-
在代理的导航菜单中,点击代理端点部分中默认下的 PreFlow。
“默认代理端点”中的“请求 PreFlow”是请求进入 API 代理时执行的第一个流。
OAuthV2 政策需要密文,因此将在 API 代理中及早执行。
-
在“流”窗格中,点击请求流中 PreFlow 旁边的 + 按钮。
-
选择创建新政策,在“中介”部分下,从选择政策下拉菜单中选择分配消息,然后将显示名称和名称设置为 AM-GetSecret。
-
点击添加。在导航菜单中,点击政策下的 AM-GetSecret。
AssignMessage 政策配置即会显示在“代码”窗格中。
-
将政策配置更改为:
<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,IgnoreUnresolvedVariables 设置会导致 AssignMessage 政策引发错误。
添加 OAuthV2 政策以验证令牌
-
在代理的导航菜单中,点击代理端点部分中默认下的 PreFlow。
OAuthV2 政策应在 AssignMessage 政策之后执行。
-
在“流”窗格中,点击请求流中 PreFlow 旁边的 + 按钮。
-
选择创建新政策,然后在选择政策下拉菜单中,从“安全性”部分选择 OAuth v2.0,然后将显示名称和名称设置为 OA-VerifyToken。
-
点击添加,然后点击导航菜单中政策下的 OA-VerifyToken。
OAuthV2 政策配置显示在“代码”窗格中。
-
将 OAuthV2 政策配置更改为:
<OAuthV2 name="OA-VerifyToken">
<Operation>VerifyJWTAccessToken</Operation>
<Algorithm>HS256</Algorithm>
<SecretKey>
<Value ref="private.secretkey"/>
</SecretKey>
</OAuthV2>
该配置指定 JWT 访问令牌将使用 HS256 (HMAC-SHA256) 算法,并使用在 AssignMessage 政策中创建的私有变量作为密钥。
-
点击保存。
点击“检查我的进度”以验证是否完成了以下目标:
添加用于验证令牌的政策
任务 3. 添加用于生成令牌的政策
系统还会向 API 代理添加一个单独的代理端点,以允许创建 JWT 令牌。
为令牌操作添加新的代理端点
在生产环境中,通常会创建一个单独的代理来生成令牌。在本实验中,您将在同一 API 代理中的单独代理端点内创建令牌生成流。
-
在代理的导航菜单中,点击代理端点行中的 + 按钮。
注意:请勿点击“默认”旁边的“+”按钮。
此操作将创建一个新的代理端点,供创建新的 JWT 时使用。
-
对于名称,指定 token,然后点击添加。
名为 token 的新代理端点将显示在“代码”窗格中。
-
将整个 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>
-
点击保存。
这一更新后的配置会产生 2 项特定更改:
-
BasePath 设置为
/token。这是创建令牌时将使用的基本路径。
-
RouteRule 不再引用目标端点。API 代理会创建一个令牌,而无需调用后端服务。
创建用于生成令牌的流
-
在代理流中,在代理端点:token 部分中,点击 /token 旁边的 +。
-
对于新的条件流,请指定以下值:
| 属性 |
值 |
| 流名称 |
generateToken |
| 条件类型 |
选择“自定义”。 |
-
对于条件,请指定以下值:
(proxy.pathsuffix MatchesPath "/") and (request.verb = "POST") and (request.formparam.grant_type = "client_credentials")
仅允许有效的客户端凭证令牌请求。
-
点击添加。
附加 AssignMessage 政策以检索属性集值
将生成令牌的 OAuthV2 政策还需要访问 private.secretkey 变量。
-
在代理的导航菜单中,点击代理端点部分中 token 下的 generateToken。
-
在“流”窗格中,点击请求流中 generateToken 右侧的 + 按钮。
-
对于选择政策,选择选择现有政策,然后点击 AM-GetSecret。
-
点击添加。
相同的 AssignMessage 政策将附加到令牌代理端点 PreFlow。
添加 OAuthV2 政策以生成令牌
-
在代理的导航菜单中,点击代理端点部分中 token 下的 generateToken。
-
在“流”窗格中,点击请求流中 generateToken 右侧的 + 按钮。
-
对于选择政策,请选择创建新政策,然后从“安全性”部分选择 OAuth v2.0,并将显示名称和名称设置为 OA-GenerateToken。
-
点击添加,然后点击政策中的 OA-GenerateToken。
OAuthV2 政策配置显示在“代码”窗格中。
-
将 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>
此配置将允许创建在 30 分钟后过期的 JWT OAuth 令牌。
针对无效的令牌请求引发错误
-
在代理流中,在代理端点:token 部分中,点击 /token 旁边的 +。
-
对于新的条件流,请指定以下值:
| 属性 |
值 |
| 流名称 |
invalidRequest |
| 条件类型 |
选择“自定义”。 |
| 条件 |
DELETETHIS |
添加流后,系统会删除该条件,因为任何无效的 generateToken 请求都应通过此流处理。
-
点击添加。
-
在 invalidRequest 流中,移除下面一行:
<Condition>DELETETHIS</Condition>
-
在代理的导航菜单中,点击代理端点部分中 token 下的 invalidRequest。
-
在“流”窗格中,点击请求流的 invalidRequest 旁边的 + 按钮。
-
选择创建新政策,然后从“中介”部分选择引发故障,并将显示名称和名称设置为 RF-InvalidTokenRequest。
-
点击添加,然后点击政策中的 RF-InvalidTokenRequest。
RaiseFault 政策配置显示在“代码”窗格中。
-
将 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”响应。
-
点击保存。
点击“检查我的进度”以验证是否完成了以下目标:
添加用于生成令牌的政策
任务 4. 部署 OAuth 代理
在此任务中,您将部署 API 代理,并确认访问需要 OAuth 令牌。
确认运行时实例可用
-
在 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 环境何时完成附加。
-
等待实例准备就绪。
当屏幕上显示文本 ***ORG IS READY TO USE*** 时,表示实例已准备就绪。Apigee 组织 (org) 可能已在您开始实验之前创建,因此您不一定需要等待实例创建完成。
如果您正在等待组织准备就绪,可以先了解 OAuth、SpikeArrest 政策、遮盖和隐藏数据,以及不透明令牌和 JWT。
部署 API 代理
-
在 Cloud 控制台中前往 Apigee。
-
在左侧导航菜单中,依次选择代理开发 > API 代理,然后点击 bank-v1。
-
点击开发标签页。
-
点击部署,为环境选择 eval。
系统会显示一个对话框,要求您确认部署。
-
对于“服务账号”,请指定服务账号的邮箱:
apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
-
点击部署和确认。
-
点击概览标签页,然后等待 eval 部署状态显示代理已部署。
点击“检查我的进度”以验证是否完成了以下目标:
部署 API 代理
测试 API 代理
Apigee 组织中的 eval 环境可以使用主机名 eval.example.com 进行调用。此主机名的 DNS 条目已在您的项目中创建,并且会解析为 Apigee 运行时实例的 IP 地址。此 DNS 条目是在专用区域中创建的,这意味着它仅在内部网络中可见。
Cloud Shell 并不位于内部网络中,因此 Cloud Shell 命令无法解析此 DNS 条目。组织内的虚拟机 (VM) 可以访问专用区域 DNS。系统自动创建了名为 apigeex-test-vm 的虚拟机。您可以使用此机器调用 API 代理。
-
在 Cloud Shell 中,打开与测试虚拟机的 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 中提出的每个问题,按 Enter 键或 Return 键来指定默认输入。
您的登录身份是项目的所有者,因此允许通过 SSH 连接到此机器。
您的 Cloud Shell 会话现在正在虚拟机内运行。
-
在 eval 环境中调用已部署的 bank-v1 API 代理:
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 代理已阻止对后端服务的访问。
-
输入命令 exit 以退出 SSH 会话并返回到 Cloud Shell。
任务 5. 添加 API 产品、开发者和应用
在此任务中,您将添加一个 API 产品,该产品将提供对您的 API 的访问权限。您还将创建一个开发者,然后创建一个与您的 API 产品关联的应用。
创建 API 产品
-
在 Cloud 控制台中前往 Apigee。
-
在左侧导航菜单中,依次选择分发 > API 产品。
-
如需创建新的 API 产品,请点击 +创建。
-
在产品详情窗格中,指定以下内容:
| 属性 |
值 |
| 名称 |
bank-readonly |
| 显示名称 |
银行(读取权限) |
| 环境 |
选择 eval
|
| 访问权限 |
选择公开
|
保持自动批准访问请求处于选中状态。
-
在操作部分中,点击 +添加操作。
操作用于指定与 API 产品关联的应用允许在哪些 API 代理中发出哪些请求。
注意:请确认该按钮位于“操作”部分,而不是“GraphQL 操作”部分。
-
指定以下内容:
| 属性 |
值 |
| API 代理 |
选择 bank-v1 API 代理 |
| 路径 |
/** |
| 方法 |
选择 GET |
路径表达式 /\*\* 表示允许任何与基本路径匹配的请求。
在生产环境中,您可能会选择单独添加允许的每项操作,而不是使用此通配符路径表达式。
-
点击保存以保存该操作。
-
如需保存 API 产品,请点击“产品详情”页面顶部的保存。
-
返回到分发 > API 产品页面。
系统会列出相应 API 产品。
创建应用开发者
在创建应用之前,您必须先创建应用开发者。
-
在左侧导航菜单中,依次点击分发 > 开发者。
-
如需创建新的应用开发者,请点击 +创建。
-
指定以下内容:
| 属性 |
值 |
| 名字 |
Joe |
| 姓氏 |
开发者 |
| 用户名 |
joe |
| 邮箱 |
joe@example.com |
-
点击添加以创建应用开发者。
创建具有 bank-v1 访问权限的应用
-
在左侧导航菜单中,依次点击分发 > 应用。
-
如需创建新应用,请点击 +创建。
-
在应用详情窗格中,指定以下内容:
| 属性 |
值 |
| 名称 |
readonly-app |
| 开发者 |
select joe@example.com |
-
在凭证窗格中,依次点击添加凭证 > 添加产品,从下拉菜单中选择银行(读取权限),然后点击添加以进行添加。
-
点击右上角的创建以创建应用。
现在,系统已为该应用配置“密钥”和“密文”。
-
点击密钥和密文旁边的显示图标。
对于此 API,需要 OAuth 访问令牌。密钥和密文将用作应用的凭证,以允许应用创建 OAuth 访问令牌。
点击“检查我的进度”以验证是否完成了以下目标:
添加 API 产品并创建应用
测试 API
-
在 Cloud Shell 中,打开与测试虚拟机的 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 会话现在正在虚拟机内运行。
-
如需获取应用的使用方密钥和密文,请运行以下命令:
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 标头中发送使用方密钥和密文,以便生成访问令牌。
-
如需生成 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 中。
-
如需使用 JWT 令牌测试请求,请使用以下命令:
curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/customers"
现在,API 调用应返回客户列表。
注意:如果您收到的响应表明“您的客户端无权访问所请求的网址”,请验证是否已在任务 1 中正确设置了受众群体。
-
输入命令 exit 以退出 SSH 会话并返回到 Cloud Shell。
任务 6. 添加速率限制
在此任务中,您将添加一个 SpikeArrest 政策,该政策将使用 API 产品配额配置来限制对 API 的调用速率。
SpikeArrest 政策可让您指定允许的最大流量速率,从而防范您的 API 和后端出现流量激增。此政策可用于确保后端不会因无法处理的流量而过载。
添加 SpikeArrest 政策以生成令牌
此 SpikeArrest 政策将针对 /token API 的调用流量指定总体速率限制。
-
在 Cloud 控制台中前往 Apigee。
-
在左侧导航菜单中,依次选择代理开发 > API 代理,然后点击 bank-v1。
-
点击开发标签页。
-
在代理的导航菜单中,点击代理端点部分中令牌下的 PreFlow。
SpikeArrest 政策应在条件流政策之前执行。
-
在“流”窗格中,点击请求流中 PreFlow 旁边的 + 按钮。
-
选择创建新政策,然后从“流量管理”部分选择高峰控制,并将显示名称和名称设置为 SA-LimitTokenRate。
-
点击添加,然后在政策部分中点击 SA-LimitTokenRate。
SpikeArrest 政策配置显示在“代码”窗格中。
-
将 SpikeArrest 政策配置更改为:
<SpikeArrest name="SA-LimitTokenRate">
<Rate>5pm</Rate>
<UseEffectiveCount>false</UseEffectiveCount>
</SpikeArrest>
此配置指定允许的最大请求速率为每分钟 5 个。所有流量都将受到此 SpikeArrest 政策的限制。
注意:每分钟 5 个请求是为了方便测试,本实验中的 SpikeArrest 限制通常太低,不适合实际应用场景。
将 UseEffectiveCount 设置为 false,意味着 SpikeArrest 政策正在使用令牌桶算法。通过将速率划分为更小的时间间隔来平滑处理流量。每分钟 5 个请求意味着每 1/5 分钟(即每 12 秒)1 个请求。如果第二个请求在第一个请求进入消息处理器后不到 12 秒就进入,则可能会被拒绝。
为 API 请求添加 SpikeArrest 政策
此 SpikeArrest 政策将针对 /bank/v1 API 的调用流量指定速率限制。此速率将按应用实施。
-
在代理的导航菜单中,点击代理端点部分中默认下的 PreFlow。
SpikeArrest 政策应在调用中尽早执行,但必须在 OAuthV2 VerifyJWTAccessToken 政策之后执行,以便根据应用限制速率。
-
在“流”窗格中,点击请求流中 PreFlow 旁边的 + 按钮。
-
选择创建新政策,然后从“流量管理”部分选择高峰控制,并将显示名称和名称设置为 SA-LimitRateByApp。
-
点击添加,然后在政策部分中点击 SA-LimitRateByApp。
SpikeArrest 政策配置显示在“代码”窗格中。
-
将 SpikeArrest 政策配置更改为:
<SpikeArrest name="SA-LimitRateByApp">
<Rate>5pm</Rate>
<Identifier ref="client_id" />
<UseEffectiveCount>true</UseEffectiveCount>
</SpikeArrest>
与上一个政策类似,此配置指定允许的最大请求速率为每分钟 5 个。不过,此政策指定了一个标识符,该标识符会针对每个 client_id 单独维护 SpikeArrest 速率。客户端 ID 由 OA-VerifyToken 政策填充,并且每个开发者应用的客户端 ID 都是唯一的。
将 UseEffectiveCount 设置为 true,意味着为区域内的所有流量维护速率计数。该政策会维护每个周期内收到的请求的计数器,若速率单位为“每分钟请求数”,则该周期为 1 分钟。速率计算基于滑动窗口。

对于上述示例,假设我们使用的速率为每分钟 50 个请求。计数器采用 1 分钟为一个周期,但如果速率单位指定为“每秒请求数”,则计数器周期会变为 1 秒。假设我们已进入当前分钟的第 10 秒,如箭头所示。前一分钟有 48 个请求,而当前周期到目前为止有 5 个请求。
若要允许再发出一个请求,则速率需低于每分钟 50 个请求。计算出的速率为:
request_rate = (48 * (60-10)/60) + 6 = 46
由于当前周期只过去了 10 秒(共 60 秒),因此剩余 50 秒的请求量将参照上一周期的速率进行计算。48 * 5/6 = 40。若允许再处理一个请求,当前周期的请求计数将变为 5+1,即 6 个。计算得出的请求速率为每分钟 46 次,表明可以允许该请求,因为此速率低于每分钟 50 个请求的限制。
-
依次点击保存 > 另存为新修订版本。
-
点击部署,然后为环境选择 eval
-
对于服务账号,请指定服务账号的邮箱:
apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
- 点击部署和确认。
- 点击概览标签页,然后等待 eval 部署状态显示代理已部署。
点击“检查我的进度”以验证是否完成了以下目标:
添加 SpinkeArrest 政策
测试速率限制
-
在 Cloud Shell 中,打开与测试虚拟机的 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 会话现在正在虚拟机内运行。
-
如需获取应用的使用方密钥和密文,请运行以下命令:
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}"
-
通过反复运行以下命令,生成多个访问令牌:
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,因此系统会使用“令牌桶”算法来平滑流量。您很可能会在第 5 个请求之前触发高峰控制违规提示。
-
如需保存 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}"
-
如需测试 API 调用的 SpikeArrest 政策,请重复发送以下命令:
curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/customers"
UseEffectiveCount 为 true,因此该政策使用滑动窗口算法。在请求被拦截之前,您应该能够成功发出 5 个请求。
-
输入命令 exit 以退出 SSH 会话并返回到 Cloud Shell。
任务 7. 数据遮盖
在此任务中,您将创建一个数据遮盖,在调试会话中隐藏特定字段。
启动调试会话
Debug 是一种用于对 Apigee 上运行的 API 代理进行问题排查和监控的工具。借助 Debug 工具,您可以在 API 调用期间检查每个步骤的详细信息。
-
在左侧导航菜单中,依次选择代理开发 > API 代理,然后点击 bank-v1。
-
点击调试标签页。
-
在启动调试会话窗格中,点击启动调试会话,然后在环境下拉菜单中选择 eval 环境。
-
点击启动。
调试会话可能需要过一段时间才能开始捕获请求。
注意:如果您在屏幕顶部附近的红色框中看到错误消息,且提示内容类似“提取调试事务时出错”或“列出调试会话事务时出错”等说明,则您的调试会话可能仍能正常运行。
您将发出 API 请求,然后检查调试会话。
调试请求
-
在 Cloud Shell 中,打开与测试虚拟机的 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 会话现在正在虚拟机内运行。
-
如需获取应用的令牌,请运行以下命令:
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}"
-
向 API 发出以下请求:
curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/customers/abe@example.org/accounts"
-
返回到 Apigee 界面。
“调试”页面应显示 2 个请求:一个 POST 请求(用于生成令牌)和一个 GET 请求(用于检索用户的账号)。
-
点击 GET 请求。
系统会显示 GET 请求详细信息。
-
点击第一个政策,即 AM-GetSecret 政策,该政策会将变量 propertyset.oauth.secret 复制到变量 private.secretkey 中。

“阶段详情”不会显示私有变量,因为前缀为“private.”的变量会在调试会话中被隐藏。不过,属性集变量会存储相同的敏感数据,因此最好对调试流量的用户隐藏该变量。
-
点击来自后端的响应,可通过工厂图标左侧的圆圈找到该响应。

响应包含用户的账号(包括账号余额)。
创建调试遮盖
-
在同一浏览器窗口中打开新标签页,然后前往 Apigee API 参考文档。
Apigee API 参考文档详细介绍了既可用于管理 Apigee,也可用于调用 Apigee API 的各种 API 调用。本页显示了 organization.environments API 调用。
-
滚动到页面底部,然后点击 updateDebugmask。
此 API 调用将更新环境的调试遮盖。
-
在“试用此 API”窗格中,对于“名称”请求参数,请使用以下内容:
organizations/{{{ project_0.project_id | PROJECT }}}/environments/eval/debugmask
-
对于请求正文,请输入以下内容:
{
"responseJSONPaths": [
"$[*].balance"
],
"variables": [
"propertyset.oauth.secret"
]
}
此载荷将导致 propertyset.oauth.secret 变量被遮盖,同时还会遮盖响应载荷的对象数组中的每个 balance 字段。
-
点击执行。
如果系统弹出窗口,要求您选择账号,请选择学生账号。
-
点击允许,以允许该网页使用学生凭证。
测试调试遮盖
-
在 Apigee 界面中,从左侧导航菜单中依次选择代理开发 > API 代理,然后点击 bank-v1。
-
点击调试标签页。
-
在启动调试会话窗格中,从环境下拉菜单中选择 eval。
-
点击启动。
-
在 Cloud Shell 中,如果 SSH 连接已关闭,请打开与测试虚拟机的 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
-
获取令牌并再次发出 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"
-
返回 Apigee 界面中的“调试”页面,然后点击 GET 请求。
-
点击 AM-GetSecret 政策。
propertyset.oauth.secret 变量已被遮盖。

-
点击后端响应所对应的代理响应流已启动。
每个 balance 字段都被遮盖。

任务 8. 错误处理
在此任务中,您将创建一个默认条件流,仅允许调用后端的特定资源,并重写后端错误消息。
测试 API
-
在 Cloud Shell 中,如果 SSH 连接已关闭,请打开与测试虚拟机的 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
-
输入 Y 继续,然后按 Enter 键两次将口令留空。
-
获取令牌并向 /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(未找到网页)”错误
故障规则可用于检测错误和重写错误消息。
系统将使用 RaiseFault 政策来设置新响应。
-
在 Cloud 控制台中前往 Apigee。
-
在左侧导航菜单中,依次选择代理开发 > API 代理,然后点击 bank-v1。
-
点击开发标签页。
-
在代理的导航菜单中,点击政策旁边的 +。
-
从“中介”部分选择引发故障,然后将显示名称和名称设置为 RF-404NotFound。
-
点击创建。在政策部分中,点击 RF-404NotFound。
-
将 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
-
在代理的导航菜单中,点击目标端点部分中的默认。
默认目标端点包含返回 404 响应的后端目标调用。404 会被视为失败代码。端点将引发故障,并且可以使用目标端点中指定的 FaultRules 来重写 API 响应。
-
在 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>
-
依次点击保存 > 另存为新修订版本。
-
点击部署,然后为环境选择 eval。
-
对于服务账号,请指定服务账号的邮箱:
apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
-
依次点击部署和确认。
-
点击概览标签页,然后等待 eval 部署状态显示代理已部署。
测试端点响应故障
-
在 Cloud Shell 中,如果 SSH 连接已关闭,请打开与测试虚拟机的 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
-
获取令牌并向 /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 条件流
现在,您可以在代理端点条件流的末尾添加一个新的条件流,以便在其他条件流均不符合其条件时引发故障,而无需依赖后端在收到意外请求时返回响应。这样可确保只有条件流中列出的操作会传递到后端。此模式可让您仅允许访问部分后端服务资源。
-
在代理的导航菜单中,前往代理端点:默认,然后在流部分点击 /bank/v1 旁边的 +。
-
对于新的条件流,请指定以下值:
| 属性 |
值 |
| 流名称 |
404NotFound |
| 条件类型 |
选择“自定义”。 |
| 条件 |
DELETETHIS |
-
点击添加。
-
在 404NotFound 流中,移除下面一行:
<Condition>DELETETHIS</Condition>
如果前面的所有条件流条件均不匹配,则会执行 404NotFound 流。
-
在代理的导航菜单中,点击代理端点部分中默认下的 404NotFound。
-
在“流”窗格中,点击 404NotFound 请求流旁边的 + 按钮。
-
对于选择政策,请选择选择现有政策,然后点击 RF-404NotFound。
-
点击添加。
-
依次选择保存 > 另存为新修订版本。
-
点击部署,然后为环境选择 eval
-
对于服务账号,请指定服务账号的邮箱:
apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
-
依次点击部署和确认。
-
点击概览标签页,然后等待 eval 部署状态显示代理已部署。
点击“检查我的进度”以验证是否完成了以下目标:
添加错误处理
测试 404 条件流
-
在 Cloud Shell 中,如果 SSH 连接已关闭,请打开与测试虚拟机的 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
-
获取令牌并向 /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 日
版权所有 2026 Google LLC 保留所有权利。Google 和 Google 徽标是 Google LLC 的商标。其他所有公司名和产品名可能是其各自相关公司的商标。