Secure Your Application on SAP Cloud Platform Cloud Foundry
本文概要
- 如何设置和配置 App Router 组件作为微服务环境的中央入口点来处理身份验证和授权
- 如何保护您的 Java 微服务,使其仅接受基于从应用路由器收到的有效 JSON Web 令牌 (JWT) 的请求
- 为您的应用程序用户分配角色和范围,并让您的后端处理授权信息
基本概念
在深入了解架构的实际设置之前,让我们快速回顾一下本教程打算采用的架构。
下图是 SAP Business Technology Platform 上运行时的用户认证流。首先我们已经有一个创建好并且正常工作的 Java 微服务。但是,您将使用所谓的应用路由器(App Router),而不是让客户直接访问这个应用程序,它有两个目的。
一方面,App Router 是进入微服务世界的通用入口点。主要思想是您可以将应用程序拆分为多个具有独立可部署性、多语言运行时和持久性以及独立团队的微服务。因此,需要一个中央入口组件来向最终客户隐藏微服务环境的复杂性。
另一方面,App Router 主要负责管理认证流程。应用路由器接收来自用户的未经身份验证的传入请求,并使用用户帐户和身份验证扩展服务 (XSUAA) 启动 OAuth2 流。 XSUAA 服务是 CloudFoundry 的 UAA 服务的 SAP 特定扩展,用于处理身份验证和授权(它可能再次将此方面委托给其他提供者,例如外部身份提供者)。如果用户在 XSUAA 进行身份验证,它将使用包含经过身份验证的用户以及他或她已被授予的所有范围的 JSON Web 令牌 (JWT) 进行响应。
JWT 由应用路由器传递给底层微服务,以便它们从这个任务中解放出来。 同时,这些微服务只能通过有效的 JWT 访问,因此可以防止未经身份验证的流量。
JWT 包含一个签名,每个微服务都需要验证该签名才能建立信任。 因此,每个服务都需要一个密钥(客户端机密或公钥)来验证此签名并拒绝任何带有无效 JWT 的请求。 因此,每个服务都必须维护与 XSUAA 的服务绑定,该服务绑定为运行时验证提供此信息, 如下图。 为了实现这一点,每个微服务都绑定到一个专用的 XSUAA 实例,该实例将此信息写入 VCAP_SERVICES 环境变量中,微服务可以使用该变量来验证任何令牌的有效性。
Set up the App Router
您将让 Cloud Foundry 在部署时自动检索应用路由器。 为此,您将首先设置必要的结构。
在项目文件夹下面新建一个 approuter 文件夹,进入该文件夹。
新建一个 package.json 文件:
{
"name": "approuter",
"dependencies": {
"@sap/approuter": "*"
},
"scripts": {
"start": "node node_modules/@sap/approuter/approuter.js"
}
}
在 approuter 文件夹内,新建一个 xs-app.json:
{
"welcomeFile": "index.html",
"routes": [{
"source": "/",
"target": "/",
"destination": "app-destination"
}]
}
在项目根目录下,新建 manifest.yml:
---
applications:
- name: approuter
routes:
- route: approuter-<subdomain>.cfapps.<region_id>.hana.ondemand.com
path: approuter
memory: 128M
buildpacks:
- nodejs_buildpack
env:
TENANT_HOST_PATTERN: 'approuter-(.*).cfapps.<region_id>.hana.ondemand.com'
destinations: '[{"name":"app-destination", "url" :"<APPLICATION_URL>", "forwardAuthToken": true}]'
services:
- my-xsuaa
将上述文件里的占位符,subdomain 替换成实际值。
通过前往子账户的概览页面,您将在 CF 主控室中找到您的子域:
Understanding the AppRouter’s manifest.yml
在 Cloud Foundry 上,每个子帐户都被分配了一个与一个租户相关联的子域。在多租户场景中,应用路由器需要知道将哪个租户(tenant)转发到 XSUAA 服务。这是通过在主机(host)中包含子域来实现的,应用路由器将从中提取它。这就是 TENANT_HOST_PATTERN 发挥作用的地方。它是一个变量,用于声明如何识别和处理 URL 中的租户的模式。我们希望主机符合 approuter-
请注意,TENANT_HOST_PATTERN 变量仅在真正的多租户应用程序中才需要,即物理部署为同一部署中的多个客户端提供服务的应用程序。假设您要构建多租户应用程序,因为它的目标是云原生开发。但是,如果您有单租户应用程序,则不需要此变量。为了实现这一点,xs-security.json 安全描述符可以声明 "tenant-mode": "dedicated"(参见下面的步骤 5)。
转到目的地条目。它是一个变量,用于声明从应用路由器到底层后端微服务的内部路由。由于您只有一个微服务,因此您可以在这里只定义一个名为 app-destination 的目的地。此 app-destination 由先前创建的 xs-app.json 文件引用。
最后但并非最不重要的服务部分声明将您自己的 XSUAA 服务实例绑定到应用路由器。此绑定将确保相应的 VCAP_SERVICES 条目包含验证来自 XSUAA 服务的任何传入 OAuth 令牌/JWT 所需的客户端 ID、客户端密钥和公钥:
Bind the XSUAA Service
现在您需要创建一个到 XSUAA 服务的服务绑定。 作为先决条件,您需要一个 xs-security.json(安全描述符)文件,其中包含有关您打算在应用程序中使用的授权范围的声明。 例如,只需声明一个 DISPLAY 范围,稍后将用于授权您的用户。 此外,还声明了一个名为 Viewer 的角色模板,它引用了我们的 DISPLAY 范围。
将此文件放入
xs-security.json:
{
"xsappname": "firstapp-<subdomain>",
"tenant-mode": "shared",
"scopes": [
{
"name": "$XSAPPNAME.Display",
"description": "display"
}
],
"role-templates": [
{
"name": "Viewer",
"description": "Required to view things in our solution",
"scope-references" : [
"$XSAPPNAME.Display"
]
}
]
}
使用命令行创建一个新的 xsuaa 服务实例:
cf create-service xsuaa application my-xsuaa -c xs-security.json
使用 cf push 将 approuter 部署到 SAP BTP CloudFoundry 环境。
之后,您应该能够使用部署的主机名从浏览器中找到应用路由器。 在我的情况下,这是 https://approuter-p1942765239trial.cfapps.eu10.hana.ondemand.com/hello ,您应该看到以下登录页面,您可以在其中使用您的用户电子邮件和密码:
输入用户名和密码之后,就看到了 hello world 这个 Java 微服务的输出:
更多Jerry的原创文章,尽在:"汪子熙":