【问题标题】:Quarkus JWT Returning Unauthorized on deploymentQuarkus JWT 在部署时返回未经授权
【发布时间】:2021-10-27 11:20:01
【问题描述】:

我有一个暴露一些 REST 端点的 Quarkus 项目。在开发模式下工作或从本地构建 docker 容器运行时都可以正常工作,那些带有 @RolesAllowed 和 @PermitAll 注释的端点按预期工作。但是当我通过以下步骤部署到 AWS 服务时:

  1. 提交到 Gitlab
  2. 运行 Gitlab CICD
  3. 将结果与配置一起发送到 AWS S3 存储桶
  4. 触发 AWS 代码管道
  5. 使用 docker 映像部署到 Elastic Bean

部署容器后,所有带有@PermitAll 的端点都可以正常工作,但带有@RolesAllowed 的端点会以401 Unauthorized 响应,发送到这些端点的令牌是有效的,格式正确且未过期。

HTTP/1.1 401 Unauthorized
Date: Mon, 25 Oct 2021 15:51:01 GMT
Content-Length: 0
Connection: keep-alive
Server: nginx/1.20.0
www-authenticate: Bearer

<Response body is empty>

Response code: 401 (Unauthorized); Time: 397ms; Content length: 0 bytes

该项目在 JDK 11 上的 Quarkus Platform 2.2.3.Final 上运行,我正在使用以下扩展

已安装的功能:[agroal、cdi、config-yaml、hibernate-orm、hibernate-orm-panache、hibernate-validator、jaeger、jdbc-h2、jdbc-mysql、mailer、narayana-jta、qute、rest-client ,rest-client-jackson,resteasy,resteasy-jackson,安全,smallrye-context-propagation,smallrye-health,smallrye-jwt,smallrye-openapi,smallrye-opentracing,swagger-ui,vertx,vertx-web]

更新:

我深入了解 Quarkus 文档并添加了一些配置并映射所有授权异常并获取日志和堆栈跟踪,但我不知道为什么会发生,因为我正在使用 que guide 在创建公共时所说的过程和私钥。此外,如果我将所有 base64 令牌放入 jwt.io 调试器中并粘贴公钥内容,则表明签名有效。

io.quarkus.security.AuthenticationFailedException
    at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator$1.accept(MpJwtValidator.java:61)
    at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator$1.accept(MpJwtValidator.java:49)
    at io.smallrye.context.impl.wrappers.SlowContextualConsumer.accept(SlowContextualConsumer.java:21)
    at io.smallrye.mutiny.operators.uni.builders.UniCreateWithEmitter.subscribe(UniCreateWithEmitter.java:22)
    at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
    at io.smallrye.mutiny.operators.uni.UniMemoizeOp.subscribe(UniMemoizeOp.java:76)
    at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
    at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
    at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
    at io.smallrye.mutiny.operators.uni.UniOnTermination.subscribe(UniOnTermination.java:21)
    at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
    at io.smallrye.mutiny.operators.uni.UniMemoizeOp.subscribe(UniMemoizeOp.java:76)
    at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
    at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:54)
    at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:61)
    at io.smallrye.mutiny.groups.UniAwait.indefinitely(UniAwait.java:42)
    at io.quarkus.security.runtime.SecurityIdentityAssociation.getIdentity(SecurityIdentityAssociation.java:66)
    at io.quarkus.security.runtime.SecurityIdentityAssociation_ClientProxy.getIdentity(SecurityIdentityAssociation_ClientProxy.zig:250)
    at io.quarkus.security.runtime.SecurityIdentityProxy.hasRole(SecurityIdentityProxy.java:38)
    at io.quarkus.security.runtime.SecurityIdentityProxy_ClientProxy.hasRole(SecurityIdentityProxy_ClientProxy.zig:401)
    at io.quarkus.security.runtime.interceptor.check.RolesAllowedCheck.apply(RolesAllowedCheck.java:55)
    at io.quarkus.security.runtime.interceptor.SecurityConstrainer.check(SecurityConstrainer.java:28)
    at io.quarkus.security.runtime.interceptor.SecurityHandler.handle(SecurityHandler.java:23)
    at io.quarkus.security.runtime.interceptor.RolesAllowedInterceptor.intercept(RolesAllowedInterceptor.java:29)
    at io.quarkus.security.runtime.interceptor.RolesAllowedInterceptor_Bean.intercept(RolesAllowedInterceptor_Bean.zig:386)
    at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
    at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
    at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
    at za.co.tenfour.controller.UserController_Subclass.findMyself(UserController_Subclass.zig:1031)
    at za.co.tenfour.controller.UserController_ClientProxy.findMyself(UserController_ClientProxy.zig:262)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
    at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
    at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
    at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
    at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:408)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:69)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
    at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
    at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
    at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
    at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:138)
    at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:93)
    at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:543)
    at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
    at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
    at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:829)\nCaused by: io.smallrye.jwt.auth.principal.ParseException: SRJWT07000: Failed to verify a token
    at io.smallrye.jwt.auth.principal.DefaultJWTTokenParser.parseClaims(DefaultJWTTokenParser.java:166)
    at io.smallrye.jwt.auth.principal.DefaultJWTTokenParser.parse(DefaultJWTTokenParser.java:56)
    at io.smallrye.jwt.auth.principal.DefaultJWTCallerPrincipalFactory.parse(DefaultJWTCallerPrincipalFactory.java:31)
    at io.smallrye.jwt.auth.principal.DefaultJWTParser.parse(DefaultJWTParser.java:60)
    at io.smallrye.jwt.auth.principal.DefaultJWTParser_ClientProxy.parse(DefaultJWTParser_ClientProxy.zig:298)
    at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator$1.accept(MpJwtValidator.java:53)
    ... 59 more\nCaused by: org.jose4j.jwt.consumer.InvalidJwtSignatureException: JWT rejected due to invalid signature. Additional details: [[9] Invalid JWS Signature: JsonWebSignature{\"typ\":\"JWT\",\"alg\":\"RS256\"}->eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovLzEwZm91ci5jby56YS9pc3N1ZXIiLCJncm91cHMiOlsiQWRtaW5pc3RyYXRvciJdLCJpYXQiOjE2MzUxOTcyMjUsImV4cCI6MTY2Njc1NDgyNSwidXBuIjoic3VwcG9ydEAxMGZvdXIuY28uemEiLCJ1aWQiOjEsImZ1bGxfbmFtZSI6IjEwRm91ciBBZG1pbmlzdHJhdG9yIiwianRpIjoiMWZmNDA4MjYtNmNhNy00NzQxLTk0Y2QtOTlhY2Q0ZGY4M2IyIn0.i8skIOrh6Et84uuASjwhQQMnIjRnfiP4zjPQAB7XsyVwSEuZEc31m9reXTW1uWjzvoZTbllYZ79Aiu4Vq7MqMPJKvXIqXhmTWbX-R9JnQoI0M_Sb1c6DAXDD_biZGYUM48-FO3lRG9XCu_qr06uT4sOb1DLwh6pjdehTwnkbMX_B1Jckn-7hStCcV04XwXOOZkZWnP6_uFltsDLIQd7PsYbnRzgO19xhaAb6sfuUeKwhTs2WJL7msj0FhH_HbeEFel5OnH_NLfPhEvzByS5VRdN9j3LRNZ5z0OOm3rK_W9A6r34VRaUvddJ2_wXiyv3hvtMKLoN8wJUJuhhjqQKtTQ]
    at org.jose4j.jwt.consumer.JwtConsumer.processContext(JwtConsumer.java:224)
    at org.jose4j.jwt.consumer.JwtConsumer.process(JwtConsumer.java:433)
    at io.smallrye.jwt.auth.principal.DefaultJWTTokenParser.parseClaims(DefaultJWTTokenParser.java:145)
    ... 64 more\n

【问题讨论】:

    标签: java amazon-web-services jwt quarkus


    【解决方案1】:

    问题在于 AWS 时区配置,出于某种奇怪的原因,它干扰了 Quarkus 如何验证令牌的 IAT 和 EXP 声明。我删除了 AWS 时区设置,并在 JVM 级别使用系统属性设置时区,问题已完全解决。

    【讨论】:

      猜你喜欢
      • 2018-11-05
      • 2018-05-19
      • 2017-01-12
      • 2018-02-02
      • 2020-08-05
      • 2018-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多