Tôi nhận được lỗi kết nối xuất hiện ngẫu nhiên khi kết nối với máy chủ HAProxy bằng SSL. Tôi đã xác nhận rằng những lỗi này xảy ra trên các phiên bản JDK 1.7.0_21 và 1.7.0_25 nhưng không phải với 1.7.0_04 hoặc với 1.6.0_38.
Trường hợp ngoại lệ là
Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397)
at SSLTest2.main(SSLTest2.java:52)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Những thất bại này chỉ xảy ra khi sử dụng bối cảnh SSL TLS và không phải với bối cảnh mặc định. Các mã sau đây được chạy trong một vòng lặp một ngàn lần và thất bại xảy ra trước khi vòng lặp hoàn thành (khoảng 2% của các kết nối thất bại):
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null, null, null);
SSLSocketFactory factory = sslcontext.getSocketFactory();
SSLSocket socket = (SSLSocket)factory.createSocket("myserver", 443);
//socket.startHandshake();
SSLSession session = socket.getSession();
session.getPeerCertificates();
socket.close();
Tuy nhiên, nếu tôi tạo ra bối cảnh SSL cách này tôi không có kết nối thất bại trên bất kỳ phiên bản Java tôi đã đề cập:
SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();
cách đầu tiên sử dụng SSLContextImpl$TLS10Context
và sau đó sử dụng SSLContextImpl$DefaultSSLContext
. Nhìn vào mã, tôi không thấy bất kỳ sự khác biệt nào có thể gây ra ngoại lệ.
Tại sao tôi nhận được lỗi và lợi ích/bất lợi của việc sử dụng cuộc gọi getDefault()
là gì?
Lưu ý: Các trường hợp ngoại lệ được nhìn thấy lần đầu tiên bằng cách sử dụng Apache HttpClient (phiên bản 4). Mã này là tập hợp con nhỏ nhất tái tạo vấn đề được thấy với HttpClient.
Đây là lỗi tôi thấy khi thêm -Djavax.net.debug=ssl
:
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT: fatal, bad_record_mac
%% Invalidated: [Session-101, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA]
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLException: Received fatal alert: bad_record_mac
main, IOException in getSession(): javax.net.ssl.SSLException: Received fatal alert: bad_record_mac
Một mẩu thông tin là các lỗi không xảy ra nếu tôi tắt Diffie-Hellman trên máy chủ proxy.
Vui lòng chạy lại với -Djavax.net.debug = ssl, bắt tay và đăng đầu ra từ lần chạy không thành công. – EJP
Chạy lại bằng tùy chọn gỡ lỗi. Đã cập nhật câu hỏi với thông tin này. Có ai có ý tưởng nào? – user2687486
Tại sao bạn thích bốn dòng mã hơn? – EJP