2010-06-22 35 views
27

Tôi đang cố kết nối với một trong các máy chủ của mình thông qua ssl, với Java. Tôi đã cố gắng rất nhiều lựa chọn ở đây là cố gắng hết sức mình:CertificateException: Không có tên phù hợp với ssl.someUrl.de tìm thấy

tôi tạo ra một jssecacerts với kịch bản recommendet: http://blogs.oracle.com/andreas/resource/InstallCert.java bằng lệnh: java InstallCert ssl.someUrl.de changeit

sau này tôi đã làm lệnh một lần thứ hai:

Loading KeyStore jssecacerts... 
Opening connection to ssl.someUrl.de:443... 
Starting SSL handshake... 

No errors, certificate is already trusted 

Server sent 1 certificate(s): 

1 Subject [email protected], CN=plesk, OU=Plesk, O=Parallels, L=Hernd 
on, ST=Virginia, C=US 
    Issuer [email protected], CN=plesk, OU=Plesk, O=Parallels, L=Hernd 
on, ST=Virginia, C=US 
    sha1 f1 0d 2c 54 05 e1 32 19 a0 52 5e e1 81 6c a3 a5 83 0d dd 67 
    md5  f0 b3 be 5e 5f 6e 90 d1 bc 57 7a b2 81 ce 7d 3d 

Enter certificate to add to trusted keystore or 'q' to quit: [1] 

tôi sao chép các tập tin vào thư mục mặc định và tôi nạp giấy chứng nhận trong Java trustStore

System.setProperty("javax.net.ssl.trustStore", "C:\\Program Files (x86)\\Java\\jre6\\lib\\security\\jssecacerts"); 
System.setProperty("javax.net.ssl.trustStorePassword","changeit"); 

Sau đó, tôi cố gắng kết nối

URL url = new URL("https://ssl.someUrl.de/"); 
URLConnection conn = url.openConnection(); 
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 

Và tôi nhận Error on line 3: (Không có tên phù hợp với ssl.someUrl.de tìm thấy)

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching ssl.someUrl.de found 

là nguyên nhân này Giấy chứng nhận Plesk mặc định hoặc là cái gì khác sai?

Setup: JRE 6.20, Netbeans 6.8, Windows7 64bit

Trả lời

39

Dường như giấy chứng nhận của máy chủ bạn đang cố gắng để kết nối với không phù hợp với hostname của nó.

Khi máy khách HTTPS kết nối với máy chủ, máy chủ xác minh rằng tên máy chủ trong chứng chỉ khớp với tên máy chủ của máy chủ. Nó không đủ để chứng chỉ được tin cậy, nó phải khớp với máy chủ bạn muốn nói chuyện. (Tương tự, ngay cả khi bạn tin tưởng hộ chiếu hợp pháp, bạn vẫn phải kiểm tra xem đó là hộ chiếu của người bạn muốn nói chuyện, không chỉ bất kỳ hộ chiếu nào bạn tin cậy là hợp pháp.)

In HTTP, điều này được thực hiện bằng cách kiểm tra xem:

  • chứng chỉ có chứa tên thay thế chủ đề DNS (đây là tiện ích mở rộng tiêu chuẩn) khớp với tên máy chủ;

  • không, CN cuối cùng của tên phân biệt chủ đề của bạn (đây là tên chính nếu bạn muốn) khớp với tên máy chủ. (Xem RFC 2818.)

Thật khó để biết tên của chủ thể là gì mà không có chứng chỉ (mặc dù, nếu bạn kết nối với trình duyệt và kiểm tra nội dung chi tiết hơn, bạn sẽ có thể thấy . nó) các chủ đề tên phân biệt có vẻ là:

[email protected], CN=plesk, OU=Plesk, O=Parallels, L=Herndon, ST=Virginia, C=US 

(nó như vậy sẽ cần phải được CN = ssl.someUrl.de thay vì CN = Plesk, nếu quý vị không có một cái tên thay thế với chủ đề DNS: ssl.someUrl.de rồi, tôi đoán là bạn không.)

Bạn có thể bỏ qua việc xác minh tên máy chủ bằng cách sử dụng HttpsURLConnection.setHostnameVerifier(..). Nó không phải là quá khó để viết một HostnameVerifier tùy chỉnh mà bybasses xác minh, mặc dù tôi sẽ đề nghị làm nó chỉ khi chứng chỉ của nó là một trong những có liên quan ở đây đặc biệt. Bạn sẽ có thể nhận được điều đó bằng cách sử dụng đối số SSLSession và phương thức getPeerCertificates() của nó.

(Thêm vào đó, bạn không cần phải đặt javax.net.ssl. * Tính theo cách mà bạn đã thực hiện nó, vì bạn đang sử dụng các giá trị mặc định anyway.)

Hoặc nếu bạn có quyền kiểm soát máy chủ mà bạn đang kết nối và chứng chỉ của nó, bạn có thể tạo chứng chỉ phù hợp với quy tắc đặt tên ở trên (CN phải đủ, mặc dù tên thay thế của chủ đề là cải tiến). Nếu chứng chỉ tự ký là đủ tốt cho những gì bạn đặt tên, hãy đảm bảo tên chung của nó (CN) là tên máy chủ mà bạn đang cố gắng nói chuyện (không có URL đầy đủ, chỉ tên máy chủ).

+0

thx Tôi đã làm điều đó với Trình xác định tên máy chủ lưu trữ. Tôi chỉ cần một kết nối được mã hóa. Chỉ có một máy khách và một máy chủ, với một htts cố định: // adress. – fehrlich

+1

Hãy nhớ rằng bạn * cần * một số hình thức xác minh danh tính mã hóa để cung cấp bảo mật. Nếu không, nó giống như trao đổi bí mật với một người bạn không biết: tuy nhiên phương pháp bí mật tốt là, điều đó không thực sự bảo vệ bạn. – Bruno

+0

nhưng tôi biết máy chủ và máy khách duy nhất (trên máy tính của tôi) và không ai có thể đọc luồng dữ liệu. Và trang https cũng được bảo vệ bằng một htaccess đơn giản. Hoặc tôi có hiểu sai không? – fehrlich

3

Tôi đã tìm ra giải pháp tốt ở đây: http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/

Nhưng vấn đề của tôi là một chút khác biệt và giải quyết nó một cách khác.

Dịch vụ web đã ở trên máy chủ từ xa. Ví dụ: https://some.remote.host/MyWebService?wsdl

Nhưng nó chỉ có sẵn cho IP cho bất kỳ khách hàng nào, nhưng chứng chỉ được tạo cho miền: some.remote.host (CN = some.remote.host). Và miền này không thể được giải quyết bằng IP bởi vì nó không được trình bày trong DNS).

Vì vậy, cùng một vấn đề xuất hiện: nếu tôi sử dụng IP để kết nối với dịch vụ web bằng ssl, nó không thể đạt được bằng chứng chỉ CN = some.remote.host và nó không bằng tên máy chủ mà tôi đã chỉ định (tức là máy chủ IP).

Tôi đã giải quyết nó bằng cách khớp tên máy chủ này với IP trong tệp/etc/hosts. Sự cố đã được khắc phục.

Nhưng trong trường hợp khi Dịch vụ web được lưu trữ trên máy chủ ứng dụng cục bộ, thì nó sẽ được giải quyết như mkyong được mô tả trong bài viết của mình.

1

Tên máy chủ nên được giống như là người đầu tiên tên/cuối cùng mà bạn cung cấp cho trong khi tạo ra một giấy chứng nhận

15

Ở Java 8 bạn có thể bỏ qua tên máy chủ kiểm tra với đoạn mã sau:

HttpsURLConnection.setDefaultHostnameVerifier ((hostname, session) -> true); 

Tuy nhiên điều này chỉ nên được sử dụng trong phát triển!

+0

tuyệt vời, cảm ơn. trợ giúp thêm ở đây: http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/ – OhadR

7

Tôi đã tạo phương thức fixUntrustCertificate(), vì vậy khi tôi đang xử lý một miền không nằm trong CA đáng tin cậy, bạn có thể gọi phương thức này trước yêu cầu. Mã này sẽ hoạt động sau java1.4. Phương pháp này áp dụng cho tất cả máy chủ:

public void fixUntrustCertificate() throws KeyManagementException, NoSuchAlgorithmException{ 


     TrustManager[] trustAllCerts = new TrustManager[]{ 
      new X509TrustManager() { 
       public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
        return null; 
       } 

       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()); 
     HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 

     HostnameVerifier allHostsValid = new HostnameVerifier() { 
      public boolean verify(String hostname, SSLSession session) { 
       return true; 
      } 
     }; 

     // set the allTrusting verifier 
     HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); 
} 
Các vấn đề liên quan