用途
在将 SAP BTP Neo 环境中的 Java 应用迁移到 Cloud Foundry 时,用于为该应用配置 SAP Application Router(approuter)。在 Neo 环境中,平台隐式处理路由和认证;而在 Cloud Foundry 中,必须显式地将 approuter 设置为独立的 Node.js 模块。approuter 作为面向 Web 的应用的唯一入口点,用于:提供静态内容(将 HTML、CSS、JavaScript 文件直接交付给客户端);通过 XSUAA 触发认证流程;重写请求 URL 以匹配路由规则;将请求转发或代理到相应的后端服务;在向其后端服务转发请求时传递用户信息(用户 ID、角色)。
主要能力
- 提供静态 UI 内容(webapp/ 下的 HTML/CSS/JS)。
- 通过 XSUAA 触发用户认证。
- 按规则重写 URL 并将请求转发或代理到后端服务。
- 向其后端转发用户信息(用户 ID、角色)。
- 支持标准与扩展两种 approuter 变体:标准变体由 XSUAA 原生处理 SAML、OIDC 与 Basic 认证;扩展变体仅在确认后端会显式发送需要客户端重定向拦截的 WWW-Authenticate 或 com.sap.cloud.security.logout 头时才使用。
使用方式
技能首先进行适用性检测。不要仅凭存在 web.xml 就调用本技能——几乎所有 Java Servlet 应用都有 web.xml。仅当存在以下显式认证/UI 信号之一时才适用:web.xml 中存在 FORM 或 XSUAA 的 auth-method、存在 security-constraint 定义;Java 源码中使用了 UserProvider/getUserPrincipal/isUserInRole;webapp/ 下有面向用户提供的静态 Web 内容;或用户明确要求设置 approuter。检测命令示例:
grep -l "auth-method|security-constraint" src/main/webapp/WEB-INF/web.xml grep -rl "UserProvider|getUserPrincipal|isUserInRole" src/main/java/ find . -name ".html" -path "/webapp/*" | head -5
当应用满足以下全部条件时应跳过本技能:web.xml 中没有 auth-method、没有 security-constraint,也没有 XSUAA resource-ref;webapp/ 下没有 .html/.css/.js(只返回 JSON/文本的 Servlet 属于纯 API);应用被直接访问(如邮件发送器、REST/JDBC 后端)。此时迁移后的应用是单个 java.tomcat 模块,直接绑定其所需服务(destination、connectivity、credstore 等),没有 approuter/ 模块、没有 xs-app.json、也没有 uaa/ias 资源。
对于无头 REST/Servlet 应用(无面向用户的 UI、无 FORM 认证)但仍需 XSUAA 进行技术令牌校验(如机器对机器调用)的情况,不应添加 approuter,而应将 XSUAA 直接绑定到 Java 模块。
前置条件:在执行本技能前需先执行 sdk-replacement 技能(设置 SAP Cloud SDK)。
变体选择(默认使用标准 approuter):标准 approuter 的启动命令为 node node_modules/@sap/approuter/approuter.js,适用于所有端点都需 XSUAA 认证、认证与公开端点混合、Neo 应用使用 SAML2 + Basic Auth 等常见场景。扩展 approuter 启动命令为 node server.js,仅当后端显式发送需要客户端重定向拦截的 WWW-Authenticate 头、或显式发送 com.sap.cloud.security.logout 头时使用。Neo 应用曾使用 SAML2 或 Basic Auth 并不意味着需要扩展 approuter。
转换步骤:
Step 1:在项目根目录创建 approuter/ 目录:mkdir -p approuter
Step 2:创建 approuter/package.json。标准 approuter 使用脚本 node node_modules/@sap/approuter/approuter.js,依赖 @sap/approuter,资料示例版本为 ^16.0.0,并提示 @sap/approuter 版本可能随时间更新,实际迁移时应查看 NPM 包页面获取最新版本。扩展 approuter 使用启动脚本 node server.js。
Step 3:创建 xs-app.json 路由配置。标准配置示例:
{ "authenticationMethod": "route", "routes": [ { "source": "^/(.*)$", "target": "/$1", "destination": "<destination-name>", "authenticationType": "xsuaa", "csrfProtection": false } ] }
其中 <destination-name> 需替换为将在 mtad.yaml 中接入的 destination 名称。资料指出,sap_java_buildpack_jakarta 始终在 /(ROOT 上下文)提供应用,仅当 web.xml 中某 Servlet 映射到 url-pattern: / 时才会额外在 /<warName>/ 注册,多数迁移应用没有该映射,因此只有 / 可用,approuter 的 target 应使用 /$1,不带 /<artifactId>/ 前缀。
对于同时含受保护与公开端点的应用,xs-app.json 可包含多条路由,受保护路由使用 authenticationType: xsuaa,公开路由使用 none,并配置 logout(logoutEndpoint 为 /logout,logoutPage 为 /)。路由按从上到下的顺序匹配,更具体的路由(如 /protected)须放在兜底路由(^(/.*))之前。
保留 Servlet 路径前缀:若后端 web.xml 将 JAX-RS/Jersey Servlet 映射到特定前缀(如 /webapi/),approuter 路由必须在 target 中保留该前缀。错误写法为 { "source": "^/webapi(/.*)?$", "target": "$1" }(会剥离 /webapi,后端 Servlet 映射无法匹配);正确写法为 { "source": "^/webapi(/.*)?$", "target": "/webapi$1" }。资料还提示:若后端同时从 WAR 的 webapp/ 目录提供静态内容,不要将 Servlet 映射改为 /,否则 Jersey 会拦截静态资源请求并返回 "Not Found"。
扩展 xs-app.json 仅在显式验证需要扩展 approuter 时使用,包含受保护路由、认证端点、Basic 认证端点、logout 回调与兜底路由等,资料警告不必要的扩展配置会引入路由复杂性并可能导致崩溃。
Step 4(仅扩展 approuter 需要):创建 approuter/server.js 与 approuter/authentication-challenge-handler.js。自定义中间件负责:拦截后端发来的 WWW-Authenticate: SAML2 realm="Identity Authentication Service" 头并重定向到 XSUAA 认证端点;拦截 WWW-Authenticate: Basic realm="SAP HANA Cloud Platform" 头并重定向到 Basic 认证端点;拦截后端的 com.sap.cloud.security.logout 头并处理登出重定向流程。资料给出了 server.js 与 authentication-challenge-handler.js 的代码示例(含 redirect、handleAuthenticationChallenge、handleLogout 函数和 insertMiddleware.beforeRequestHandler 中间件)。
适用场景
- 具有面向用户认证(web.xml 中有 FORM 或 XSUAA auth-method、security-constraint)且迁移到 Cloud Foundry 的 Web 应用。
- 需要在 webapp/ 下向用户提供静态 HTML/CSS/JS 的 Java 应用。
- Java 源码中使用 UserProvider/getUserPrincipal/isUserInRole 的应用。
- 用户明确要求设置或配置 approuter 的迁移场景。
限制
- 不应基于 web.xml 的存在与否来判断是否使用本技能;纯后端应用(REST API、邮件、持久化、文档管理、keystore)不得添加 approuter,否则会创建无支撑模块并破坏部署;标准 approuter 的 xs-app.json 绑定 XSUAA,缺失该服务时模块会因
Cannot find service uaa in environment: No service matches uaa(以及 ias)而启动失败。 - 若为纯 API 应用强行添加 approuter,路由映射需由添加者自行负责;当 WAR 上下文根非根路径(如 document-management.war 在 /document-management 而非 / 提供服务)且 xs-app.json 的 route target 未考虑该前缀时,所有请求会静默返回 404(应用与 approuter 均健康)。
- 对于仅需 XSUAA 技术令牌校验的无头后端应用,应直接将 XSUAA 绑定到 Java 模块,不添加 approuter。
- 资料未提供 approuter 的价格、收费或平台支持范围等信息。