Micronaut中如何实现Bearer JWT令牌校验完成请求认证鉴权
Micronaut 接收外部JWT Bearer令牌校验实现
Micronaut Security JWT模块已经内置了JWT签名校验、exp字段有效期校验的核心逻辑,你不需要重复实现这部分能力,只需要补充必填声明的自定义校验规则,再调整配置关闭框架自带的令牌生成相关能力即可适配你的场景,具体步骤如下:
1. 引入依赖
根据你的构建工具引入micronaut-security-jwt模块即可,这是JWT校验能力的核心依赖:
- Gradle 配置:
implementation("io.micronaut.security:micronaut-security-jwt") - Maven 配置:对应引入上述坐标的依赖即可
2. 基础配置调整
因为你不需要框架提供用户名密码登录、JWT生成的能力,只需要做入站令牌校验,所以在application.yml中添加如下配置:
micronaut: security: # 认证方式指定为Bearer令牌 authentication: bearer token: jwt: # 配置JWT签名校验规则,根据你的实际签名方式选一种即可 signatures: # 方式1:用JWKS拉取公钥校验(适配OAuth2/OIDC颁发的令牌) jwks: default: url: ${JWT_JWKS_URL:http://your-internal-auth-service/.well-known/jwks.json} # 方式2:用对称密钥校验(适用于内部服务共享密钥签发令牌的场景) # secret: # default: # secret: ${JWT_SIGN_SECRET:your-256-bit-secret} # 关闭内置的访问令牌生成能力,不需要框架颁发JWT generator: access-token: enabled: false # 开启请求头Bearer令牌解析 bearer: enabled: true
配置完成后,框架默认就会拦截所有请求,校验请求头
Authorization: Bearer <token>中的JWT签名合法性、是否超出exp字段标记的有效期,这两项校验不通过会直接返回401。
3. 实现必填声明自定义校验
你只需要注册一个JwtClaimValidator类型的Bean,框架会自动把它加入JWT校验链路,在签名、有效期校验通过后执行你的自定义声明校验:
import io.micronaut.core.annotation.NonNull; import io.micronaut.security.token.Claims; import io.micronaut.security.token.jwt.validator.JwtClaimValidator; import jakarta.inject.Singleton; import java.util.List; @Singleton public class RequiredClaimsValidator implements JwtClaimValidator<Claims> { // 替换为你业务要求的必填声明列表 private static final List<String> MANDATORY_CLAIMS = List.of("user_id", "scope", "org_id"); @Override public boolean validate(@NonNull Claims claims) { // 所有必填声明存在且值非空时返回校验通过 return MANDATORY_CLAIMS.stream() .allMatch(claimKey -> { Object claimValue = claims.get(claimKey); return claimValue != null && !claimValue.toString().isBlank(); }); } }
如果需要自定义校验失败的返回报文(比如统一业务错误码格式),自己实现AuthenticationFailureHandler接口并注册为Bean即可替换默认的401响应逻辑。
4. 控制器层使用
你之前规划的@Secured(IS_AUTHENTICATED)注解可以直接使用,不需要额外适配:
import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.security.annotation.Secured; import io.micronaut.security.rules.SecurityRule; @Controller("/api/biz") public class BusinessController { @Get("/info") @Secured(SecurityRule.IS_AUTHENTICATED) public String getBizInfo() { return "请求认证通过,正常返回业务数据"; } }
额外说明
- 不需要自己手写全局拦截器做校验,框架的安全过滤器会自动按顺序执行所有校验规则,校验通过后会把认证信息注入安全上下文,你可以在业务代码中直接注入
Authentication对象拿到JWT中的声明内容 - 只有当你的JWT不使用标准
exp字段存储过期时间时,才需要额外自定义过期校验逻辑,标准场景完全不需要重复开发
内容的提问来源于stack exchange,提问作者Sandy
相关产品推荐
相关产品推荐

