Quarkus中JWT认证下@RolesAllowed始终返回403问题排查
问题场景
我在Module X的控制器中有一个受@RolesAllowed注解保护的接口方法:
@GET @RolesAllowed("admin") public Response findAllPriceRequests() { return Response.ok(serviceX.findAllPrices()).build(); }
另有一个Module Y-jwt模块,负责生成JWT的接口代码如下:
public String generateJwt() { Set<String> roles = new HashSet<>( List.of("admin") ); long duration = System.currentTimeMillis() + 3600; return Jwt.issuer("y-jwt") .subject("y-jwt") .groups(roles) .expiresAt(duration) .sign(); }
模块配置
Module Y-jwt的application.properties:
quarkus.http.port=8082 smallrye.jwt.sign.key.location=../jwt/privateKey.pem smallrye.jwt.path.groups=roles
Module X的application.properties:
quarkus.swagger-ui.always-include=true mp.jwt.verify.issuer=immo-jwt mp.jwt.verify.publickey.location=../jwt/publicKey.pem smallrye.jwt.path.groups=roles
密钥生成命令
mkdir jwt openssl genrsa -out jwt/rsaPrivateKey.pem 2048 -ii openssl rsa -pubout -in jwt/rsaPrivateKey.pem -out jwt/publicKey.pem openssl pkcs8 -topk8 -nocrypt -inform pem -in jwt/rsaPrivateKey.pem -outform pem -out jwt/privateKey.pem
依赖配置
Module X添加的依赖:
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-jwt</artifactId> </dependency>
Module Y-jwt添加的依赖:
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-jwt-build</artifactId> </dependency>
问题描述
当使用Module Y-jwt生成的JWT调用Module X的GET接口时,始终返回403 Forbidden。我判断认证通过但授权失败,请问问题出在哪里?
更新后的JWT生成代码
之后我修改了生成JWT的代码,但问题依旧:
public String generateJwt() { Set<String> roles = new HashSet<>( List.of("admin, writer") ); long duration = System.currentTimeMillis() + 3600; return Jwt.issuer("y-jwt") .subject("y-jwt") .groups(roles) .expiresAt(duration) .sign(); }
问题根源与修复方案
Issuer不匹配(核心问题)
Module X配置的mp.jwt.verify.issuer=immo-jwt,但JWT生成时指定的issuer是"y-jwt",Quarkus会严格校验JWT的issuer字段是否与配置一致,这直接导致认证失败,进而返回403。
修复:将JWT生成代码中的issuer("y-jwt")改为issuer("immo-jwt"),保持与Module X的配置一致。角色格式错误
更新后的代码中List.of("admin, writer")是把包含逗号的单个字符串作为一个角色,实际JWT的roles字段会是["admin, writer"],与接口要求的admin角色不匹配。
修复:改为List.of("admin", "writer"),生成两个独立的角色条目。过期时间设置错误
System.currentTimeMillis() + 3600是给JWT设置了3.6秒的有效期,生成后很快就会过期,调用时会因JWT过期返回403。
修复:改为System.currentTimeMillis() + 3600 * 1000,设置1小时的有效期。验证角色映射
确保smallrye.jwt.path.groups=roles配置生效,JWT的claims中groups字段会被映射到roles字段,与@RolesAllowed的校验逻辑匹配。
内容的提问来源于stack exchange,提问作者Jan D.M.

