调用REST接口遇javax.crypto.AEADBadTagException,curl/Postman正常
问题:Java应用调用HTTPS接口出现SSL Tag mismatch错误
运行在Payara 6上的J2EE 10应用调用GET JSON REST接口时,出现javax.crypto.AEADBadTagException: Tag mismatch错误,具体信息及排查情况如下:
错误堆栈信息
jakarta.ws.rs.ProcessingException: javax.net.ssl.SSLException: Tag mismatch at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:270) at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:300) at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:675) at org.glassfish.jersey.client.JerseyInvocation.call(JerseyInvocation.java:697) at org.glassfish.jersey.client.JerseyInvocation.lambda$runInScope$3(JerseyInvocation.java:691) at org.glassfish.jersey.internal.Errors.process(Errors.java:292) at org.glassfish.jersey.internal.Errors.process(Errors.java:274) at org.glassfish.jersey.internal.Errors.process(Errors.java:205) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:390) at org.glassfish.jersey.client.JerseyInvocation.runInScope(JerseyInvocation.java:691) at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:674) at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:422) at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:318) at com.tm2builder.careeronestop.CosBuilder.getOccupationJsonResponse(CosBuilder.java:696) at com.tm2builder.careeronestop.CosUtils.processGetOccupationData(CosUtils.java:236) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.glassfish.expressly.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:186) at org.glassfish.expressly.parser.AstValue.invoke(AstValue.java:253) at org.glassfish.expressly.MethodExpressionImpl.invoke(MethodExpressionImpl.java:248) at org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40) at org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50) at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:70) at com.sun.faces.application.ActionListenerImpl.getNavigationOutcome(ActionListenerImpl.java:74) at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:62) at jakarta.faces.component.UICommand.broadcast(UICommand.java:205) at jakarta.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:858) at jakarta.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1332) at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:56) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:72) at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:159) at jakarta.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:691) at jakarta.faces.webapp.FacesServlet.service(FacesServlet.java:449) at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1554) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:331) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:211) at com.tm2builder.util.SetEncodingFilter.doFilter(SetEncodingFilter.java:92) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:253) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:211) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:257) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:166) at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:757) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:577) at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:158) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:372) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:239) at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:520) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:217) at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:174) at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:153) at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:196) at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:88) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:246) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:178) at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:118) at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:96) at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:51) at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:510) at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:82) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:83) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:101) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:535) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:515) at java.base/java.lang.Thread.run(Thread.java:1583) Caused by: javax.net.ssl.SSLException: Tag mismatch at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:132) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:378) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:316) at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:123) at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506) at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1421) at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455) at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426) at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:586) at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:187) at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1675) at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1599) at java.base/java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:531) at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:307) at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:423) at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:268) ... 64 more Caused by: javax.crypto.AEADBadTagException: Tag mismatch at java.base/com.sun.crypto.provider.GaloisCounterMode$GCMDecrypt.doFinal(GaloisCounterMode.java:1652) at java.base/com.sun.crypto.provider.GaloisCounterMode.engineDoFinal(GaloisCounterMode.java:458) at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2543) at java.base/sun.security.ssl.SSLCipher$T13GcmReadCipherGenerator$GcmReadCipher.decrypt(SSLCipher.java:1908) at java.base/sun.security.ssl.SSLSocketInputRecord.decodeInputRecord(SSLSocketInputRecord.java:264) at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:181) at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:111) ... 76 more
调用接口的curl命令
curl --location 'https://api.careeronestop.org/v1/occupation/KTlBjGthMe8nDlZ/11-1011.00/0?wages=true&projectedEmployment=true&videos=true' --header 'Content-Type: application/json' --header 'Authorization: Bearer *********'
各环境测试表现
- curl在所有实例及家用电脑上均每次成功
- Postman在Windows家用电脑上每次成功
- Java应用在某AWS VPC的Amazon Linux 2023实例上每次成功
- 在另一AWS VPC的Amazon Linux 2023实例上,即使使用正常实例的镜像,Java应用每次调用都失败,但curl仍正常
- 家用电脑上的同应用调用偶尔成功
已尝试的排查动作
- 更换多种HTTP客户端:Jersey、Apache HttpClient、HttpClient5,结果一致
- 更换JDK版本:17、21、22,无改善
- 重新安装Payara,使用全新AL2023实例及应用,问题依旧
- 对比工作与非工作实例的Java安全策略,未发现差异
- 确认AWS安全组及网络ACL均允许HTTPS 443出站及所有入站流量
解决方向
1. 强制Java客户端使用非GCM加密套件
错误根源是GCM加密的Tag校验失败,curl和Postman可能默认协商的是其他加密套件(如CBC)。可通过JVM参数指定禁用GCM或优先使用其他套件:
# 禁用GCM加密算法 -Djdk.tls.disabledAlgorithms=GCM # 或者指定优先使用TLSv1.2及非GCM套件 -Djdk.tls.client.protocols=TLSv1.2 -Dhttps.protocols=TLSv1.2
2. 检查VPC内的网络中间设备
非工作VPC内的NAT网关、防火墙、代理可能存在SSL流量改写或Inspection机制,干扰了Java的SSL握手流程。可临时绕过这些设备测试,或检查设备的SSL配置是否兼容GCM加密。
3. 启用SSL调试日志定位差异
添加JVM参数开启SSL握手详细日志,对比工作与非工作实例的加密套件协商过程:
-Djavax.net.debug=ssl:handshake:verbose
重点查看Cipher Suite字段,确认两边是否协商了不同的加密套件,以此定位问题点。
4. 验证JVM SSL配置细节
再次检查工作与非工作实例的$JAVA_HOME/conf/security/java.security文件,重点关注以下配置项:
jdk.tls.disabledAlgorithmsjdk.tls.ephemeralDHKeySizejdk.tls.rejectClientInitiatedRenegotiation
确保配置完全一致,避免细微差异导致的问题。
内容的提问来源于stack exchange,提问作者Mike Russiello
相关产品推荐
相关产品推荐

