1. 简介
对 Web 应用的用户进行身份验证通常是必要的,并且通常需要在应用中进行特殊编程。对于 Google Cloud Platform 应用,您可以将这些职责交给 Identity-Aware Proxy 服务。如果您只需要限制选定用户具有访问权限,则无需对应用进行任何更改。如果应用需要知道用户的身份(例如,为了在服务器端保留用户的偏好),只需编写极少的应用代码,Identity-Aware Proxy 即可提供该功能。
什么是 Identity-Aware Proxy?
Identity-Aware Proxy (IAP) 是一项 Google Cloud Platform 服务,可用于拦截发送到您应用的 Web 请求、对使用 Google Identity Service 发出请求的用户进行身份验证,并且仅当请求来自您授权的用户时,才允许通过。此外,它还可以修改请求标头,在其中包含有关经过身份验证的用户的信息。
此 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
列出了应用使用的所有非默认 Python 库,app.yaml
用于告知 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 群组地址或 G Suite 域名)都添加为成员。点击“添加成员”。输入您的电子邮件地址,然后选择要分配给该地址的 Cloud IAP/IAP-Secured Web App User 角色。您可以采用相同的方式输入更多地址或 G Suite 网域。 |
点击“保存”。窗口底部会显示“政策已更新”消息。
返回您的应用并重新加载页面。您现在应该可以看到自己的 Web 应用,因为您已使用授权的用户登录。不过,您可能仍会看到“您没有访问权限”提示,因为 IAP 可能不会重新检查您的授权。在这种情况下,请执行以下步骤:
- 打开网络浏览器,转到首页地址,并在网址末尾添加
/_gcp_iap/clear_login_cookie
,例如https://iap-example-999999.appspot.com/_gcp_iap/clear_login_cookie
。 - 您将看到一个新的“使用 Google 账号登录”屏幕,并且您的账号已显示在其中。请勿点击该账号,而应点击“使用其他账号”,然后重新输入您的凭据。
- 这会让 IAP 重新检查您的访问权限,您现在应该能看到应用的首页。
如果您有权访问其他浏览器,或能够在浏览器中使用无痕模式,并且拥有其他有效的 GMail 或 G Suite 账号,则可以使用该浏览器转到您的应用页面,然后使用另一个账号登录。由于该账号尚未获得授权,因此浏览器会显示“您没有访问权限”页面,而不是您的应用。
4. 第 2 步 - 访问用户身份信息
一旦应用受到 IAP 保护,它就可以使用 IAP 在所传递的 Web 请求标头中提供的身份信息。在此步骤中,该应用将获取已登录用户的电子邮件地址,以及 Google Identity 服务分配给该用户的永久性唯一身份用户 ID。该数据将在欢迎页面中显示给用户。
这是第 2 步,最后一步是在 iap-codelab/1-HelloWorld
文件夹中打开 Cloud Shell。切换到此步骤的文件夹:
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 步,也是最后一步,也就是在 iap-codelab/2-HelloUser
文件夹中打开 Cloud Shell。切换到此步骤的文件夹:
cd ~/iap-codelab/3-HelloVerifiedUser
部署到 App Engine
将应用部署到 Python 3.7 版 App Engine 标准环境:
gcloud app deploy
当系统询问您是否要继续时,请输入 Y 表示“是”。部署应该会在几分钟内完成。等待期间,您可以按照如下所述检查应用文件。
部署准备就绪后,您会看到一条消息,提示您可以使用 gcloud app browse
查看应用。输入该命令。如果浏览器中没有打开新标签页,请复制所显示的链接,按常规的方法在新标签页中将其打开。
回想一下,您在第 2 步中停用了 IAP,因此没有向应用提供任何 IAP 数据。您应该会看到如下所示的页面:
与之前一样,您可能需要等待几分钟,直到最新版本生效后才能看到页面的新版本。
由于 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 实例。您每次部署应用时,系统都会创建一个新版本,该版本将继续存在,直到将其删除。退出实验即可删除项目及其中的所有资源。