如何使用Azure OAuth或Azure API网关保护Open XPage REST API
基于Azure的Xpages REST API服务器到服务器认证保护方案
当前实现分析
你目前在Xpages的REST服务代码中直接通过Azure的JWKS端点验证Bearer令牌,这种方式可行但耦合性高,所有验证逻辑都嵌入业务代码,后续维护和扩展不便。以下是更优的替代保护方案:
方案一:Azure API网关前置认证
将Azure API网关部署在Xpages API前端,让网关全权承担OAuth令牌验证工作,具体步骤:
- 配置API网关实例:创建网关并将后端指向你的Xpages API端点
- 添加JWT验证策略:在网关的API操作中配置「验证JWT」策略,关键参数包括:
- 令牌颁发者:
https://login.microsoftonline.com/{租户ID}/v2.0 - JWKS URI:
https://login.microsoftonline.com/{租户ID}/discovery/v2.0/keys - 允许的受众:你的API对应的客户端ID或应用ID URI
- 令牌颁发者:
- 收紧后端访问权限:修改Xpages数据库权限,仅允许API网关的IP地址访问,取消Anonymous的直接访问权限,确保所有请求必须经过网关校验
这种方案的核心优势:
- 业务代码无需处理认证逻辑,专注于业务实现
- 网关统一处理令牌验证、限流、日志监控等横切需求
- 后端API不直接暴露给外部,安全性大幅提升
方案二:结合Azure AD应用角色实现细粒度授权
如果需要更精准的权限控制,可以基于Azure AD应用角色扩展验证逻辑:
- 在Azure AD的API应用注册中添加自定义应用角色(例如
LocationUpload.Write) - 为调用API的客户端应用分配对应的应用角色
- 令牌验证时,额外检查
roles声明是否包含所需权限
修改后的验证逻辑示例(中文注释):
<xe:restService pathInfo="locationupload"> <xe:this.service> <xe:customRestService> <xe:this.doPost><![CDATA[#{javascript:try { // Azure JWKS公钥地址 var azureDiscoveryKeys = "https://login.microsoftonline.com/租户ID/discovery/v2.0/keys"; // 从请求头获取Bearer令牌 var token = context.getRequest().getHeader("Authorization").replace("Bearer ", ""); var provider = new UrlJwkProvider(new URL(azureDiscoveryKeys)); var jwt = JWT.decode(token); var jwk = provider.get(jwt.getKeyId()); var publicKey = (RSAPublicKey) jwk.getPublicKey(); // 配置验证算法和规则 var alg = Algorithm.RSA256(publicKey, null); var verifier = JWT.require(alg) .withIssuer("https://login.microsoftonline.com/租户ID/v2.0") .withAudience("你的API应用ID URI") .build(); var decodedJwt = verifier.verify(token); // 检查令牌中的应用角色权限 var roles = decodedJwt.getClaim("roles").asList(String.class); if (!roles.contains("LocationUpload.Write")) { throw new Exception("无权限访问该API"); } System.out.println("令牌验证通过,权限检查通过"); } catch(JWTVerificationException ex) { System.out.println("令牌验证失败:" + ex.getMessage()); context.getResponse().setStatus(401); } catch(JwkException ex) { System.out.println("获取公钥失败:" + ex.getMessage()); context.getResponse().setStatus(500); } catch(MalformedURLException ex) { System.out.println("JWKS URL格式错误:" + ex.getMessage()); context.getResponse().setStatus(500); } catch(Exception e) { System.out.println("请求处理失败:" + e.getMessage()); context.getResponse().setStatus(403); e.printStackTrace(); }}]]></xe:this.doPost> </xe:customRestService> </xe:this.service> </xe:restService>
方案三:Azure AD B2C(适配未来扩展场景)
若后续需要支持用户参与的认证流程,可以考虑Azure AD B2C,但当前服务器到服务器无交互场景下必要性较低。
关键注意事项
- 令牌获取方式:确保客户端使用「客户端凭据流」(Client Credentials Flow)获取令牌,这是无用户交互场景的标准OAuth 2.0流程
- 权限最小化原则:收紧Xpages数据库权限,避免Anonymous权限过大;若使用API网关,仅开放网关IP的访问权限
- 性能优化:当前代码每次请求都拉取JWKS公钥,建议添加缓存逻辑,减少对Azure端点的重复请求
内容的提问来源于stack exchange,提问作者Vijayakumar Oorappan
相关产品推荐
相关产品推荐

