如何不使用Spring Boot/Security实现对接Azure AD的Java OAuth2资源服务器
基于Azure AD实现非Spring体系OAuth2资源服务器的方案
完全可以脱离Spring Boot/Security生态实现该需求,针对Jersey框架的Java Web项目可以参考以下落地方案:
1. 依赖选择
无需引入Spring相关依赖,可选用两类通用组件实现:
- 通用JWT处理库:
com.nimbusds:nimbus-jose-jwt,用于完成JWT解析、签名校验逻辑,无框架绑定属性 - 可选:微软官方轻量Azure身份认证SDK,无需依赖Spring,可简化部分配置逻辑
2. 核心实现逻辑
OAuth2资源服务器的核心能力是校验请求携带的Access Token合法性,你可以通过Jersey的过滤器统一实现该能力,无需侵入业务代码:
2.1 定义全局认证过滤器
@Provider public class AzureAdAuthFilter implements ContainerRequestFilter { private static final String AUTHORIZATION_HEADER = "Authorization"; private static final String BEARER_PREFIX = "Bearer "; @Override public void filter(ContainerRequestContext requestContext) throws IOException { String authHeader = requestContext.getHeaderString(AUTHORIZATION_HEADER); // 无合法认证头直接返回401 if (authHeader == null || !authHeader.startsWith(BEARER_PREFIX)) { requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build()); return; } String accessToken = authHeader.substring(BEARER_PREFIX.length()); boolean tokenValid = validateAzureAdToken(accessToken); if (!tokenValid) { requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build()); return; } // 校验通过后可将用户信息、权限存入请求上下文供业务接口使用 } }
2.2 实现Azure AD Token校验逻辑
针对Azure AD发放的Token,需要完成以下核心校验项:签名合法性、发行方、受众、有效期、权限范围
private boolean validateAzureAdToken(String token) { try { // 解析JWT头获取密钥ID,匹配Azure AD公开密钥 JWSHeader header = JWSHeader.parse(new JWT(token).getHeader().toJSONObject()); String kid = header.getKeyID(); // 拉取Azure AD租户公开密钥集,生产环境建议做本地缓存降低请求耗时 JWKSet jwkSet = JWKSet.load(new URL("https://login.microsoftonline.com/你的Azure租户ID/discovery/v2.0/keys")); JWK matchedKey = jwkSet.getKeyByKeyId(kid); if (matchedKey == null) return false; // 校验Token签名,防止伪造 JWSVerifier verifier = new RSASSAVerifier((RSAKey) matchedKey); SignedJWT signedJWT = SignedJWT.parse(token); if (!signedJWT.verify(verifier)) return false; // 校验核心声明字段 JWTClaimsSet claims = signedJWT.getJWTClaimsSet(); String expectedIssuer = "https://login.microsoftonline.com/你的Azure租户ID/v2.0"; String expectedAudience = "你在Azure AD注册的资源服务器客户端ID"; if (!expectedIssuer.equals(claims.getIssuer())) return false; if (!expectedAudience.equals(claims.getAudience().get(0))) return false; if (claims.getExpirationTime().before(new Date())) return false; if (claims.getNotBeforeTime().after(new Date())) return false; // 可选:校验接口要求的访问权限 List<String> scopes = claims.getStringListClaim("scp"); if (!scopes.contains("业务要求的权限标识")) return false; return true; } catch (Exception e) { return false; } }
3. Jersey集成配置
只需要将过滤器注册到Jersey配置中即可生效:
@ApplicationPath("/api") public class JerseyAppConfig extends ResourceConfig { public JerseyAppConfig() { register(AzureAdAuthFilter.class); packages("你的业务接口包路径"); } }
内容的提问来源于stack exchange,提问作者MaHo
相关产品推荐
相关产品推荐

