Spring Boot(Tomcat 9)对接Azure B2C认证时频繁出现「无法获取远程JWK集:读取超时」问题求助
解决Spring Boot + Azure B2C JWT验证超时问题
我之前碰到过几乎一模一样的Azure B2C JWK集获取超时问题,结合你给出的技术栈(Java 11、Tomcat 9、Spring Boot 2.5.7等),可以尝试以下几个解决方案:
1. 自定义JWK请求的超时参数
默认情况下,Nimbus的DefaultResourceRetriever使用的超时时间偏短(连接超时500ms,读取超时500ms),这很容易在网络波动时触发超时。你可以自定义JwtDecoder,调整这些超时值:
import com.nimbusds.jose.jwk.source.RemoteJWKSet; import com.nimbusds.jose.jwk.source.JWKSource; import com.nimbusds.jose.proc.SecurityContext; import com.nimbusds.jose.util.DefaultResourceRetriever; import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; import org.springframework.context.annotation.Bean; @Bean public JwtDecoder jwtDecoder() { String jwkSetUri = "https://<your-b2c-tenant>.b2clogin.com/<your-b2c-tenant>.onmicrosoft.com/<your-policy>/discovery/v2.0/keys"; // 自定义资源获取器,设置更长的超时时间 DefaultResourceRetriever resourceRetriever = new DefaultResourceRetriever( 5000, // 连接超时(毫秒) 10000 // 读取超时(毫秒) ); JWKSource<SecurityContext> jwkSource = new RemoteJWKSet<>( URI.create(jwkSetUri), resourceRetriever ); return NimbusJwtDecoder.withJwkSetUri(jwkSetUri) .jwkSource(jwkSource) .build(); }
然后确保你的AADJwtBearerTokenAuthenticationConverter使用这个自定义的JwtDecoder。
2. 启用JWK本地缓存
每次请求都远程拉取JWK集是低效且容易超时的,你可以配置本地缓存来复用已获取的JWK:
方式一:使用Nimbus自带的缓存
RemoteJWKSet支持设置缓存刷新间隔,比如每30分钟刷新一次:
RemoteJWKSet<SecurityContext> remoteJWKSet = new RemoteJWKSet<>( URI.create(jwkSetUri), resourceRetriever ); // 设置缓存刷新间隔为30分钟 remoteJWKSet.setRefreshTime(30, TimeUnit.MINUTES);
方式二:结合Spring Cache
如果你的项目已经启用了Spring Cache,可以对JWK获取逻辑添加缓存注解,减少远程请求次数。
3. 排查网络与防火墙限制
首先确认Tomcat所在服务器能够正常访问Azure B2C的JWK端点:
- 用
curl命令测试连通性:curl -v https://<your-b2c-tenant>.b2clogin.com/<your-b2c-tenant>.onmicrosoft.com/<your-policy>/discovery/v2.0/keys - 检查服务器防火墙、代理是否允许出站请求到Azure B2C的域名(
b2clogin.com) - 如果使用代理,需要在JVM参数中配置代理:
-Dhttp.proxyHost=your-proxy-host -Dhttp.proxyPort=your-proxy-port -Dhttps.proxyHost=your-proxy-host -Dhttps.proxyPort=your-proxy-port
4. 优化Spring Security的认证过滤器顺序
有时候过滤器顺序不当会导致请求延迟,确保BearerTokenAuthenticationFilter的优先级合理,避免不必要的前置处理消耗时间。
额外调试建议
- 开启更详细的日志,添加日志配置:
这样可以看到JWK请求的具体耗时和细节,帮助定位问题。<logger name="com.nimbusds.jose" level="DEBUG"/> <logger name="org.springframework.security.oauth2.jwt" level="DEBUG"/>
内容的提问来源于stack exchange,提问作者Jeebus
相关产品推荐
相关产品推荐

