1. 简介
对 Web 应用的用户进行身份验证往往很有必要,而这通常需要在应用中进行特殊编程。对于 Google Cloud Platform 应用,您可以将这些任务交给 Identity-Aware Proxy 服务来处理。如果您只需要限制选定用户具有访问权限,则无需对应用进行任何更改。如果应用需要知道用户的身份(例如,为了在服务器端保留用户的偏好),只需编写极少的应用代码,Identity-Aware Proxy 即可提供该功能。
什么是 Identity-Aware Proxy?
Identity-Aware Proxy (IAP) 是一项 Google Cloud Platform 服务,可拦截发送给应用的 Web 请求,使用 Google Identity 服务对发出请求的用户进行身份验证,并仅允许来自已获授权的用户的请求通过。此外,它还可以修改请求标头,在其中包含有关经过身份验证的用户的信息。
此 Codelab 将引导您完成以下操作:创建自己的应用、限制对该应用的访问权限,以及从 IAP 获取用户身份。
构建内容
在此 Codelab 中,您将使用 Google App Engine 构建一个很小的 Web 应用,然后尝试通过多种方式使用 Identity-Aware Proxy 限制对该应用的访问并向该应用提供用户身份信息。您的应用将:
|
|
学习内容
- 如何使用 Python 3.7 编写和部署简单的 App Engine 应用
- 如何启用和停用 IAP 以限制对应用的访问权限
- 如何将 IAP 中的用户身份信息传递给应用
- 如何以加密方式验证 IAP 中的信息以防范仿冒行为
所需条件
- 新版网络浏览器,例如 Chrome。
- 具备 Python 编程语言的基础知识
本 Codelab 主要会用到 Google App Engine 和 IAP。对于不相关的概念,我们仅会略作介绍,但是会提供相应代码块供您复制和粘贴。
2. 准备工作
您将在 Cloud Shell 命令行环境中操作。首先,打开该环境并从中获取示例代码。
启动控制台和 Cloud Shell
在实验页面左上角,点击“打开 Google 控制台”按钮。您将需要使用该按钮下方显示的用户名和密码登录。 |
|
本 Codelab 中的所有命令都将在为您创建并打开的项目中的 Cloud Shell 内执行。点击控制台页面标题右侧的“激活 Cloud Shell”图标,打开 Cloud Shell。您可以在页面下半部分输入并运行命令。这些命令可以从您自己的 PC 运行,但您必须先安装并配置所需的开发软件。Cloud Shell 已包含您所需的所有软件工具。 |
|
下载代码
点击 Cloud Shell 中的命令行区域,以便可以输入命令。从 GitHub 获取代码,然后切换到代码文件夹:
git clone https://github.com/googlecodelabs/user-authentication-with-iap.git
cd user-authentication-with-iap
对于本 Codelab 中的每个步骤,此文件夹都包含一个相应的子文件夹。您需要切换到正确的文件夹来执行相应的步骤。
3. 第 1 步 - 部署应用并使用 IAP 对它加以保护
这是一个用 Python 3.7 编写的 App Engine 标准应用,只会显示“Hello, World”欢迎页面。我们将对它进行部署和测试,然后使用 IAP 来限制对它的访问权限。
检查应用代码
从项目主文件夹切换到包含此步骤对应代码的 1-HelloWorld 子文件夹。
cd 1-HelloWorld
应用代码位于 main.py 文件中。应用使用 Flask Web 框架通过模板的内容来对 Web 请求做出响应。该模板文件位于 templates/index.html。在此步骤中,它仅包含纯 HTML。第二个模板文件位于 templates/privacy.html,它包含框架性的隐私权政策示例。
另外还有两个文件:requirements.txt 和 app.yaml,前者列出应用所使用的所有非默认 Python 库,后者告诉 Google Cloud Platform 这是一个 Python 3.7 App Engine 应用。
您可以使用 cat 命令在 shell 中列出每个文件,如下所示:
cat main.py
或者,您也可以通过点击 Cloud Shell 窗口右上角的铅笔图标打开 Cloud Shell 代码编辑器,然后按照上面的方法检查代码。
在这一步您无需更改任何文件。
部署到 App Engine
现在,将应用部署到适用于 Python 3.7 的 App Engine 标准环境
gcloud app deploy
系统可能会要求您选择要部署到的区域。选择附近任何一家“支持标准”的门店。当系统询问您是否要继续时,请输入 Y 表示“是”。
几分钟后,部署就会完成,此时您将看到一条消息,提示您可以使用 gcloud app browse 查看应用。输入该命令。如果浏览器中没有打开新标签页,请点击显示的链接将其在新标签页中打开,或者将其复制到手动打开的新标签页(如果必要)。由于这是此应用首次运行,因此要在云实例启动后才会显示,此过程需要几秒钟时间。您应该会看到下面的窗口。

从任何连接到互联网的计算机打开该网址都可以看到该网页。访问权限尚未受到限制。
使用 IAP 限制访问权限
在 Cloud 控制台窗口中,点击页面左上角的菜单图标,然后依次点击“安全”和“Identity-Aware Proxy”。 |
|
由于这是您第一次为此项目启用身份验证选项,您会看到一条消息,要求您必须先配置 OAuth 权限请求页面,然后才能使用 IAP。 |
|
点击“配置权限请求页面”按钮。系统会打开一个新标签页,用于配置权限请求页面。 |
|
在必填空白字段中填写适当的值:
应用名称 | IAP 示例 |
支持人员电子邮件地址 | 您的电子邮件地址。系统可能已为您填写此字段。 |
已获授权的网域 | 应用网址的主机名部分,例如 iap-example-999999.appspot.com。您可以在之前打开的 Hello World 网页的地址栏中看到此信息。请不要输入网址开头的 |
应用首页链接 | 您用于查看应用的网址 |
应用隐私权政策链接 | 应用中的隐私权页面链接,由首页链接后跟 /privacy 构成 |
点击“保存”。系统会提示您创建凭据。您无需在本 Codelab 中创建凭据,因此只需关闭此浏览器标签页即可。
返回 Identity-Aware Proxy 页面并刷新。您现在应该会看到可以保护的资源列表。点击“App Engine 应用”行“IAP”列中的切换按钮,开启 IAP。 |
|
您将看到将受到 IAP 保护的域名。点击“开启”。 |
|
现在,打开浏览器标签页并访问您应用的网址。系统会显示“使用 Google 账号登录”屏幕,要求您登录以访问该应用。 |
|
使用 Google 或 G Suite 账号登录。您会看到拒绝您访问的屏幕。 |
|
您已成功使用 IAP 保护您的应用,但尚未指示 IAP 允许哪些账号通过。
返回控制台的 Identity-Aware Proxy 页面,选中 App Engine 应用旁边的复选框,页面右侧随即显示边栏。 |
|
您需要将每个允许访问的电子邮件地址(或者 Google 群组地址或 GSuite 域名)添加为成员。点击“添加成员”。输入您的电子邮件地址,然后选择为该地址分配 Cloud IAP/IAP-Secured Web 应用用户角色。您可以通过同样的方式输入更多地址或 GSuite 域名。 |
|
点击“保存”。窗口底部会显示“政策已更新”消息。
返回您的应用并重新加载页面。您现在应该可以看到自己的 Web 应用,因为您已经以授权用户的身份登录。不过,由于 IAP 可能不会重新检查您是否获得授权,因此您可能仍然会看到“您没有访问权限”页面。在这种情况下,请执行以下步骤:
- 打开网络浏览器,访问首页地址,并在网址末尾添加
/_gcp_iap/clear_login_cookie,如https://iap-example-999999.appspot.com/_gcp_iap/clear_login_cookie。 - 您将看到一个新的“使用 Google 账号登录”屏幕,并且您的账号已显示在其中。请勿点击该账号,而应点击“使用其他账号”,然后重新输入您的凭据。
- 这会让 IAP 重新检查您的访问权限,您现在应该能看到应用的首页。
如果您可以使用其他浏览器,或可以在浏览器中使用无痕模式,并且有另一个有效的 Gmail 或 GSuite 账号,则可以使用该浏览器访问您的应用页面,然后使用其他账号登录。由于该账号尚未获得授权,因此浏览器会显示“您没有访问权限”页面,而不是您的应用。
4. 第 2 步 - 访问用户身份信息
一旦应用受到 IAP 保护,它就可以使用 IAP 在所传递的 Web 请求标头中提供的身份信息。在此步骤中,该应用将获取已登录用户的邮箱,以及 Google Identity 服务分配给该用户的永久性唯一身份用户 ID。该数据将在欢迎页面中显示给用户。
这是第 2 步,上一步结束时,您的 Cloud Shell 处于 iap-codelab/1-HelloWorld 文件夹中。切换到此步骤所对应的文件夹:
cd ~/iap-codelab/2-HelloUser
部署到 App Engine
由于部署需要几分钟的时间,因此首先将应用部署到适用于 Python 3.7 的 App Engine 标准环境:
gcloud app deploy
当系统询问您是否要继续时,请输入 Y 表示“是”。部署应该会在几分钟后完成。等待期间,您可以按照如下所述检查应用文件。
部署就绪后,您会看到一条消息,提示您可以使用 gcloud app browse 查看应用。输入该命令。如果浏览器中没有打开新标签页,请复制所显示的链接,按常规的方法在新标签页中将其打开。您应该会看到如下所示的页面:

新版应用替换之前的版本可能需要几分钟的时间,请耐心等候。如果需要,请刷新页面,直到看到与上图类似的页面。
检查应用文件
此文件夹包含的文件集与第 1 步中的相同,但有两个文件发生了改变:main.py 和 templates/index.html。程序已改为检索 IAP 在请求标头中提供的用户信息,并且模板现在会显示这些数据。
main.py 中有两行代码用于获取 IAP 提供的身份数据:
user_email = request.headers.get('X-Goog-Authenticated-User-Email')
user_id = request.headers.get('X-Goog-Authenticated-User-ID')
X-Goog-Authenticated-User- 标头由 IAP 提供,并且名称不区分大小写,因此,如果您愿意,可以将它们全部小写或全部大写。render_template 语句现在包含这些值,因此应用可以显示这些信息:
page = render_template('index.html', email=user_email, id=user_id)
index.html 模板可以通过将名称括在双花括号中来显示这些值:
Hello, {{ email }}! Your persistent ID is {{ id }}.
如您所见,提供的数据带有 accounts.google.com 前缀,用于指出信息来源。如果需要,您的应用可以移除冒号前的所有内容(包括冒号)以获取原始值。
关闭 IAP
如果 IAP 被停用或以某种方式被绕过(例如,被同一个云项目中运行的其他应用绕过),此应用会发生什么情况?我们关闭 IAP 来看看。
在 Cloud 控制台窗口中,点击页面左上角的菜单图标,然后依次点击“安全”和“Identity-Aware Proxy”。点击 App Engine 应用旁边的 IAP 切换开关,关闭 IAP。 |
|
系统会显示警告,指出这样会允许所有用户访问该应用。
刷新应用网页。您应该会看到相同的页面,但没有任何用户信息:

由于应用现在不受保护,用户可以发送似乎已通过 IAP 检查的 Web 请求。例如,您可以在 Cloud Shell 中运行以下 curl 命令来执行此操作(将 <your-url-here> 替换为应用的确切网址):
curl -X GET <your-url-here> -H "X-Goog-Authenticated-User-Email: totally fake email"
网页将显示在命令行上,如下所示:
<!doctype html>
<html>
<head>
<title>IAP Hello User</title>
</head>
<body>
<h1>Hello World</h1>
<p>
Hello, totally fake email! Your persistent ID is None.
</p>
<p>
This is step 2 of the <em>User Authentication with IAP</em>
codelab.
</p>
</body>
</html>
应用无法知道 IAP 已被停用或绕过。对于存在潜在风险的情况,第 3 步给出了解决方案。
5. 第 3 步 - 使用加密验证
如果存在 IAP 被关闭或绕过的风险,应用可以检查并确保收到的身份信息有效。这需要用到 IAP 添加的第三个 Web 请求标头,即 X-Goog-IAP-JWT-Assertion。标头的值是一个以加密方式签名的对象,其中还包含用户身份数据。您的应用可以验证数字签名,并使用此对象中提供的数据来确定签名由 IAP 提供且未经篡改。
数字签名验证流程需要执行几个额外的步骤,例如检索最新的一组 Google 公钥。您可以根据有人可能能够关闭或绕过 IAP 的风险以及应用的敏感性,来决定您的应用是否需要这些额外的步骤。
这是第 3 步,上一步结束时,您的 Cloud Shell 处于 iap-codelab/2-HelloUser 文件夹中。切换到此步骤所对应的文件夹:
cd ~/iap-codelab/3-HelloVerifiedUser
部署到 App Engine
将应用部署到适用于 Python 3.7 的 App Engine 标准环境:
gcloud app deploy
当系统询问您是否要继续时,请输入 Y 表示“是”。部署应该会在几分钟后完成。等待期间,您可以按照如下所述检查应用文件。
部署就绪后,您会看到一条消息,提示您可以使用 gcloud app browse 查看应用。输入该命令。如果浏览器中没有打开新标签页,请复制所显示的链接,按常规的方法在新标签页中将其打开。
提醒一下,您在第 2 步中停用了应用内购买,因此应用不会提供任何应用内购买数据。您应该会看到如下所示的页面:

与之前一样,您可能需要等待几分钟,直到最新版本生效后才能看到页面的新版本。
由于 IAP 已停用,因此未提供用户信息。现在重新开启 IAP。
在 Cloud 控制台窗口中,点击页面左上角的菜单图标,然后依次点击“安全”和“Identity-Aware Proxy”。点击 App Engine 应用旁边的 IAP 切换开关,再次开启 IAP。 |
|
刷新页面。页面应如下所示:

请注意,验证方法所提供的电子邮件地址没有 accounts.google.com: 前缀。
如果 IAP 被关闭或绕过,则已验证数据将会缺失或无效,因为该数据不可能具有有效的签名,除非它是由 Google 私钥持有者创建的。
检查应用文件
此文件夹包含的文件集与第 2 步中相同,但有两个文件发生了改变,并增加了一个新文件。新文件是 auth.py,其中提供了 user() 方法来检索并验证以加密方式签名的身份信息。发生改变的文件是 main.py 和 templates/index.html,它们现在会使用该方法的结果。另外,还显示了第 2 步中发现的未经验证的标头以供比较。
新功能主要在 user() 函数中:
def user():
assertion = request.headers.get('X-Goog-IAP-JWT-Assertion')
if assertion is None:
return None, None
info = jwt.decode(
assertion,
keys(),
algorithms=['ES256'],
audience=audience()
)
return info['email'], info['sub']
assertion 是指定的请求标头中提供的以加密方式签名的数据。代码使用一个库来验证和解码这些数据。验证功能使用 Google 提供的公钥来检查所签名的数据,并了解数据是为哪个受众群体准备的(本质上是受保护的 Google Cloud 项目)。辅助函数 keys() 和 audience() 会收集并返回这些值。
已签名对象包含我们需要的两部分数据:经过验证的电子邮件地址和唯一 ID 值(在 sub [表示订阅方] 标准字段中提供)。
第 3 步到这里就完成了。
6. 总结
您部署了一个 App Engine Web 应用。在第 1 步中,您限制只有所选用户具有应用的访问权限。在第 2 步中,您检索并显示了 IAP 允许访问应用的用户身份,并了解了如果 IAP 被停用或绕过,这些信息可能会如何被仿冒。在第 3 步中,您验证了以加密方式签名的用户身份断言,这些断言是无法仿冒的。
7. 清理
在此 Codelab 中,您使用的唯一 Google Cloud Platform 资源是 App Engine 实例。每次部署应用时,系统都会创建一个新版本,并且该版本会一直存在,直到被删除。退出实验以删除项目及其中的所有资源。











