Spring Webflux+JJWT解析JWT时Blocking Call问题解决求助
问题描述
使用Kotlin、Spring Webflux和JJWT 0.12.6开发JWT生成与解析功能时,BlockHound检测到解析流程存在阻塞调用,根源是SecureRandom.nextBytes()触发了文件IO阻塞。堆栈信息显示阻塞发生在JJWT内部静态类初始化阶段(EcdhKeyAlgorithm、Randoms等类的加载),JWT生成功能已通过指定NativePRNGNonBlocking类型的SecureRandom解决阻塞问题,但解析流程暂无对应配置方式。
当前解析代码:
val claims: Jws<Claims> = Jwts.parser() .verifyWith(Keys.hmacShaKeyFor(secret.toByteArray())) .build() .parseSignedClaims(token)
解决方案
方法1:全局配置非阻塞SecureRandom(推荐)
JJWT支持全局设置SecureRandom实例,所有涉及随机数生成的逻辑都会复用该实例,从根源避免阻塞:
- 创建全局非阻塞
SecureRandom实例:
private val nonBlockingSecureRandom = SecureRandom.getInstance("NativePRNGNonBlocking")
- 在应用启动阶段设置全局实例(比如通过
@PostConstruct或Webflux启动钩子):
import io.jsonwebtoken.Jwts import javax.annotation.PostConstruct @PostConstruct fun initJJWTSecureRandom() { Jwts.setSecureRandom(nonBlockingSecureRandom) }
设置完成后,JWT生成与解析流程都会使用这个非阻塞的随机数生成器,不会再触发FileInputStream的阻塞调用。
方法2:提前触发静态类初始化(备选)
如果无法全局配置,可在应用启动时提前触发JJWT内部静态类的初始化,将阻塞操作转移到启动阶段(需在非Reactor主线程执行):
import io.jsonwebtoken.Jwts import reactor.core.publisher.Mono import reactor.core.scheduler.Schedulers // 在应用启动类中添加 fun initJJWTOnStartup() { Mono.fromCallable { // 触发Jwts.parser()的静态初始化 Jwts.parser().build() }.subscribeOn(Schedulers.boundedElastic()) .subscribe() }
这种方法仅将阻塞操作转移到启动阶段,后续解析请求不会再触发,但未从根源替换阻塞的SecureRandom,优先级低于方法1。
验证
修改后重新用BlockHound检测,解析接口的阻塞调用应会消失。
内容的提问来源于stack exchange,提问作者suw0n
相关产品推荐
相关产品推荐

