如何解决Spring TCP SSL中无主题备用名称的问题
Spring Integration TCP Outbound Gateway SSL连接出现“No subject alternative names present”错误
我尝试通过SSL使用TCP Outbound Gateway连接服务器,采用ClientConnectionFactory实现,同时用自定义TcpNetSSLSupport信任所有证书用于测试,但抛出了“No subject alternative names present”错误。但直接用Socket创建SSL连接并信任所有证书时,不会出现这个问题。
相关实现代码
1. ClientConnectionFactory Bean
@Bean public AbstractClientConnectionFactory nibssClientConnectionFactory() { TcpNetClientConnectionFactory factory = new TcpNetClientConnectionFactory("196.6.103.10", 55533); factory.setSerializer(customIsoMessageSerializer); factory.setDeserializer(customIsoMessageDeserializer); factory.setSingleUse(true); DefaultTcpNetSSLSocketFactorySupport defaultTcpNetSSLSocketFactorySupport = new DefaultTcpNetSSLSocketFactorySupport(customTcpNetSslContextSupport); factory.setTcpSocketFactorySupport(defaultTcpNetSSLSocketFactorySupport); return factory; }
2. TcpOutboundGateway Bean
@Bean @ServiceActivator(inputChannel = "tcpNibssOutgateChannel") public MessageHandler tcpNibssOutboundGateway() { TcpOutboundGateway gateway = new TcpOutboundGateway(); gateway.setConnectionFactory(nibssClientConnectionFactory()); gateway.setUnsolicitedMessageChannel(unsolicitedChannel()); return gateway; }
3. 自定义TcpNetSSLContextSupport
@Component public class CustomTcpNetSslContextSupport implements TcpSSLContextSupport { @Override public SSLContext getSSLContext() throws GeneralSecurityException, IOException{ SSLContext result; try { TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); result = sslContext; } catch (NoSuchAlgorithmException | KeyManagementException e) { throw new RuntimeException("Failed to create SSL context", e); } return result; } }
异常堆栈信息
javax.net.ssl.SSLHandshakeException: No subject alternative names present at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na] at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:378) ~[na:na] at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321) ~[na:na] at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:316) ~[na:na] at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:654) ~[na:na] at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473) ~[na:na] at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369) ~[na:na] at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396) ~[na:na] at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:480) ~[na:na] at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:458) ~[na:na] at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:201) ~[na:na] at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172) ~[na:na] at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1510) ~[na:na] at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1425) ~[na:na] at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455) ~[na:na] at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:925) ~[na:na] at java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:1016) ~[na:na] at java.base/java.io.InputStream.readNBytes(InputStream.java:409) ~[na:na] at java.base/java.io.InputStream.readAllBytes(InputStream.java:346) ~[na:na] at com.redtech.terminalmanagement.services.transactionManagement.utils.CustomIsoMessageDeserializer.deserialize(CustomIsoMessageDeserializer.java:62) ~[classes/:na] at com.redtech.terminalmanagement.services.transactionManagement.utils.CustomIsoMessageDeserializer.deserialize(CustomIsoMessageDeserializer.java:9) ~[classes/:na] at org.springframework.integration.ip.tcp.connection.TcpNetConnection.getPayload(TcpNetConnection.java:149) ~[spring-integration-ip-6.3.0.jar:6.3.0] at org.springframework.integration.ip.tcp.connection.TcpMessageMapper.toMessage(TcpMessageMapper.java:176) ~[spring-integration-ip-6.3.0.jar:6.3.0] at org.springframework.integration.ip.tcp.connection.TcpMessageMapper.toMessage(TcpMessageMapper.java:63) ~[spring-integration-ip-6.3.0.jar:6.3.0] at org.springframework.integration.mapping.InboundMessageMapper.toMessage(InboundMessageMapper.java:43) ~[spring-integration-core-6.3.0.jar:6.3.0] at org.springframework.integration.ip.tcp.connection.TcpNetConnection.receiveAndProcessMessage(TcpNetConnection.java:215) ~[spring-integration-ip-6.3.0.jar:6.3.0] at org.springframework.integration.ip.tcp.connection.TcpNetConnection.run(TcpNetConnection.java:206) ~[spring-integration-ip-6.3.0.jar:6.3.0] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na] at java.base/java.lang.Thread.run(Thread.java:840) ~[na:na] Caused by: java.security.cert.CertificateException: No subject alternative names present at java.base/sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:142) ~[na:na] at java.base/sun.security.util.HostnameChecker.match(HostnameChecker.java:101) ~[na:na] at java.base/sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:458) ~[na:na] at java.base/sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:432) ~[na:na] at java.base/sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(SSLContextImpl.java:1475) ~[na:na] at java.base/sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:1442) ~[na:na] at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:638) ~[na:na] ... 25 common frames omitted 2024-07-13T19:50:41.542+01:00 ERROR 17516 --- [terminal-management] [pool-2-thread-2] o.s.i.ip.tcp.TcpOutboundGateway : Tcp Gateway exception
可正常运行的直接Socket代码
socket(ipAddress, port, byteToBeSent, true); private String socket(String ipAddress, String port, byte[] byteReq, boolean isSSL) throws IOException { DataInputStream dIn = null; DataOutputStream dOut = null; String st = null; try { if (!isSSL) { Socket socket = new Socket(ipAddress, Integer.parseInt(port)); dOut = new DataOutputStream(socket.getOutputStream()); dIn = new DataInputStream(socket.getInputStream()); dOut.write(byteReq); st = dIn.readLine(); log.info("st {} is {}", isSSL, st); dOut.close(); dIn.close(); socket.close(); } else { TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted( X509Certificate[] certs, String authType) { } public void checkServerTrusted( X509Certificate[] certs, String authType) { } }}; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); SSLSocketFactory factory = sc.getSocketFactory(); SSLSocket socket = (SSLSocket) factory.createSocket(ipAddress, Integer.parseInt(port)); //Socket socket = new Socket("196.6.103.10", 55533); dOut = new DataOutputStream(socket.getOutputStream()); dIn = new DataInputStream(socket.getInputStream()); dOut.write(byteReq); st = dIn.readLine(); log.info("st isSsl true is {}", st); dOut.close(); dIn.close(); socket.close(); } } catch (Exception e) { throw new TmsIsoException("Socket connection exception after sending stream to host"); } return st; }
内容的提问来源于stack exchange,提问作者serethewind
相关产品推荐
相关产品推荐

