如何为java_websocket仅配置TLSv1.3?禁用旧协议后握手报错解决
为java_websocket仅启用TLSv1.3的配置方案
你遇到的javax.net.ssl.SSLHandshakeException: Received fatal alert: protocol_version异常,本质是客户端与服务端SSL协议版本不匹配——禁用旧版协议后,java_websocket默认SSL配置未明确指定仅使用TLSv1.3,导致握手协商失败。
以下是仅启用TLSv1.3的具体配置步骤:
1. 创建仅支持TLSv1.3的SSLSocketFactory
通过自定义SSLSocketFactory,强制指定SSL协议仅为TLSv1.3:
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocketFactory; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.security.NoSuchAlgorithmException; public class TLS13SocketFactoryProvider { public static SSLSocketFactory getTLS13OnlySocketFactory() throws NoSuchAlgorithmException { // 初始化TLSv1.3上下文 SSLContext sslContext = SSLContext.getInstance("TLSv1.3"); sslContext.init(null, null, null); // 使用默认信任/密钥管理器,如需自定义可替换参数 // 设置仅启用TLSv1.3协议 SSLParameters sslParams = sslContext.getDefaultSSLParameters(); sslParams.setProtocols(new String[]{"TLSv1.3"}); // 包装原生SSLSocketFactory,确保所有创建的Socket都应用TLSv1.3参数 return new SSLSocketFactory() { private final SSLSocketFactory delegate = sslContext.getSocketFactory(); @Override public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { Socket socket = delegate.createSocket(s, host, port, autoClose); ((javax.net.ssl.SSLSocket) socket).setSSLParameters(sslParams); return socket; } @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { Socket socket = delegate.createSocket(host, port); ((javax.net.ssl.SSLSocket) socket).setSSLParameters(sslParams); return socket; } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { Socket socket = delegate.createSocket(host, port, localHost, localPort); ((javax.net.ssl.SSLSocket) socket).setSSLParameters(sslParams); return socket; } @Override public Socket createSocket(InetAddress host, int port) throws IOException { Socket socket = delegate.createSocket(host, port); ((javax.net.ssl.SSLSocket) socket).setSSLParameters(sslParams); return socket; } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { Socket socket = delegate.createSocket(address, port, localAddress, localPort); ((javax.net.ssl.SSLSocket) socket).setSSLParameters(sslParams); return socket; } }; } }
2. 在WebSocketClient中应用自定义SocketFactory
初始化WebSocketClient时,将上述自定义的SSLSocketFactory传入:
import org.java_websocket.client.WebSocketClient; import org.java_websocket.handshake.ServerHandshake; import java.net.URI; import java.net.URISyntaxException; public class CustomWebSocketClient extends WebSocketClient { public CustomWebSocketClient(URI serverUri) { super(serverUri); try { // 设置仅支持TLSv1.3的Socket setSocket(TLS13SocketFactoryProvider.getTLS13OnlySocketFactory().createSocket()); } catch (Exception e) { e.printStackTrace(); } } @Override public void onOpen(ServerHandshake handshakedata) { System.out.println("WebSocket连接已建立"); } @Override public void onMessage(String message) { System.out.println("收到消息: " + message); } @Override public void onClose(int code, String reason, boolean remote) { System.out.println("连接关闭,原因: " + reason); } @Override public void onError(Exception ex) { ex.printStackTrace(); } public static void main(String[] args) throws URISyntaxException { // 替换为你的WebSocket服务地址 WebSocketClient client = new CustomWebSocketClient(new URI("wss://your-server-domain/path")); client.connect(); } }
关键注意事项
- Java版本要求:Java 11及以上默认支持TLSv1.3;Java 8需升级至u261及以上版本,且需通过JVM参数
-Djdk.tls.client.protocols=TLSv1.3启用。 - 服务端兼容性:必须确保服务端已启用TLSv1.3,否则仍会出现握手失败。
- 自定义证书:若需使用自定义信任证书,可在
sslContext.init()方法中传入自定义的TrustManager数组,替换默认的信任管理器。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

