You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 23:23:12