2012-04-10 36 views
6

Tôi có tên máy chủ ngoại lệ sai. Tôi đã sử dụng this code (đã nhận nó từ một số liên kết) trong chương trình program.My của tôi đang làm việc tốt. Câu hỏi của tôi có đủ an toàn không ?? (Vì nó không được xác nhận dây chuyền giấy chứng nhận)tên máy chủ sai ngoại lệ

public class Host { 

    public String subscribe() throws Exception { 
     String resp = ""; 
     String urlString="https://xxx.xxx.xx.xx:8443/WebApplication3/NewServlet"; 
     URL url; 
     URLConnection urlConn; 
     DataOutputStream printout; 
     DataInputStream input; 
     String str = ""; 
     int flag=1; 

     try { 
      HostnameVerifier hv = new HostnameVerifier() { 
       public boolean verify(String urlHostName, SSLSession session) { 
        System.out.println("Warning: URL Host: " + urlHostName + " vs. " 
         + session.getPeerHost()); 
        return true; 
       } 
      }; 

      trustAllHttpsCertificates(); 
      HttpsURLConnection.setDefaultHostnameVerifier(hv); 

      url = new URL(urlString); 
      urlConn = url.openConnection(); 
      urlConn.setDoInput(true); 
      Object object; 
      urlConn.setUseCaches(false); 

      urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 
      input = new DataInputStream(urlConn.getInputStream()); 

      while (null != ((str = input.readLine()))) { 
       if (str.length() >0) { 
        str = str.trim(); 
        if(!str.equals("")) { 
         //System.out.println(str); 
         resp += str; 
        } 
       } 
      } 
      input.close(); 
     } catch (MalformedURLException mue) { 
      mue.printStackTrace(); 
     } catch(IOException ioe) { 
      ioe.printStackTrace(); 
     } 
     return resp; 
    } 

    public static class miTM implements javax.net.ssl.TrustManager, 
     javax.net.ssl.X509TrustManager { 

     public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
      return null; 
     } 

     public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) { 
      return true; 
     } 

     public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) { 
      return true; 
     } 

     public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { 
      return; 
     } 

     public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { 
      return; 
     } 
    } 

    private static void trustAllHttpsCertificates() throws Exception { 

     // Create a trust manager that does not validate certificate chains: 
     javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; 

     javax.net.ssl.TrustManager tm = new miTM(); 

     trustAllCerts[0] = tm; 

     javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL"); 

     sc.init(null, trustAllCerts, null); 

     javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 

    } 

} 
+2

Vui lòng đăng mã của bạn (không có dòng nhận xét) như một phần của câu hỏi của bạn. – MByD

+0

@Binyamin Sharet: Đã đăng mã như một phần của câu hỏi của tôi. – user10101

+0

> Câu hỏi của tôi đủ an toàn?

Trả lời

4

Các mã trong miTM thực sự vô hiệu hóa bất kỳ kiểm tra an ninh SSL, vì vậy mức độ bảo mật là khá thấp (bạn sẽ chỉ nhận lỗi nếu giấy chứng nhận SSL được chia nhưng bạn don' t nhận được lỗi khi chứng chỉ không khớp với tên miền).

Về cơ bản, bạn cố gắng tạo kết nối mà không cần bất kỳ bảo mật nào. Nếu đó là những gì bạn muốn, giải pháp có thể là "đủ an toàn" nhưng rất có thể, câu trả lời là "không".

Giải pháp đúng cho loại sự cố này là tạo chứng chỉ phù hợp cho miền này.

Thật không may, điều này là không thể khi máy chủ HTTP của bạn đang sử dụng "lưu trữ ảo" (= nhiều tên miền ánh xạ tới cùng một địa chỉ IP). Giải pháp chính xác cho vấn đề này là lấy địa chỉ IP của riêng bạn.

Nếu bạn vẫn muốn thử một giải pháp Java mà thôi, có một cái nhìn tại câu trả lời này: https://stackoverflow.com/a/3293720/34088

+0

: Tôi đã thấy liên kết này quá ... Trên thực tế mã của tôi thuộc về một trong các liên kết (kết thúc bằng -> tutorialid = 211) được đưa ra trong liên kết đó.SO giải pháp là gì ?? – user10101

+0

Loại bỏ 'trustAllHttpsCertificates()'. Đặt 'HostnameVerifier' là đủ. –

+0

Chỉ cần nhận xét dòng tin cậyAllHttpsCertificates(); trong phương pháp dịch vụ ... chỉ cần vô hiệu hóa các cuộc gọi của chức năng là nó đủ ?? – user10101

1

Dưới đây là một cách để làm sạch mã của bạn và duy trì an toàn. Tôi cho rằng mã kết nối với một dịch vụ đã biết (đáng tin cậy). Để làm cho ngăn xếp SSL SSL chấp nhận kết nối ngay cả với tên máy chủ không khớp, cách tốt nhất là thêm chứng chỉ máy chủ vào kho lưu trữ tin cậy JVM.

Trước tiên, bạn có thể xuất chứng chỉ máy chủ từ trình duyệt của mình và lưu nó trên đĩa. Từ Linux, bạn có thể sử dụng openssl s_client -connect xxx.xxx.xx.xx:8443 và sao chép/paster chứng chỉ máy chủ ở định dạng được bọc bằng ascii thành tệp văn bản.

Sau đó nhập các chứng chỉ máy chủ vào jre/lib/security/cacerts tập tin JKS với keytool

keytool -import -alias myservice -file servercertificate.cer 

Một tùy chọn khác tôi thích, để tránh hồi quy khi Java được cập nhật, là để sao chép cacerts tại chỗ của riêng bạn và tuyên bố nó nhờ vào sự javax.net.ssl.trustStore thuộc tính hệ thống.

Khi chứng chỉ máy chủ nằm trong kho lưu trữ tin cậy ... nó được tin cậy, cho đến khi nó hết hạn. Điều này thường được sử dụng cho chứng chỉ máy chủ tự ký.

1

nhiều lần trong java sử dụng để có được loại đó của ngoại lệ

vấn đề có thể là ipconflict/ip-miền không phù hợp/không hợp lệ giấy chứng nhận

tôi đã giải quyết nó bằng cách sử dụng địa chỉ IP thích hợp của nó và cài đặt chứng chỉ.

1

Để tạo kết nối an toàn, bạn PHẢI (ít nhất):

  • xác minh rằng bạn tin tưởng vào chứng chỉ,
  • xác minh tên máy chủ (trừ khi bạn biết chắc chắn rằng đây là một và chỉ có chứng chỉ mà bạn tin tưởng có lẽ).

Mã của bạn không thành công trên hai điểm:

  • Các TrustManager bạn đang sử dụng không kiểm tra giấy chứng nhận ở tất cả (nó không bao giờ ném một ngoại lệ, trong khi API hy vọng nó để ném một hình thức của CertificateException khi chứng chỉ không đáng tin cậy).
  • Trình xác minh tên máy chủ của bạn luôn trả về true.

Để khắc phục mã của bạn:

  • Giữ các nhà quản lý tin tưởng mặc định, hoặc khởi tạo chúng với cửa hàng tin tưởng của riêng bạn và mặc định TrustManagerFactory.
  • Giữ trình xác minh tên máy chủ lưu trữ mặc định.

Tiêu đề của câu hỏi của bạn ("tên máy chủ sai ngoại lệ") và ví dụ của bạn URL https://xxx.xxx.xx.xx:8443 dường như cho thấy bạn đang kết nối đến một địa chỉ IP.

Không giống như một số trình duyệt, Java theo đặc điểm kỹ thuật (RFC 2818) khá chặt chẽ về vấn đề này:

Nếu một phần mở rộng SubjectAltName loại dNSName hiện diện, mà phải được sử dụng như danh tánh. Nếu không, (cụ thể nhất) Common Trường tên trong trường Chủ đề của chứng chỉ PHẢI được sử dụng. Mặc dù việc sử dụng Tên thông thường là thực tế hiện tại, nhưng không được sử dụng và Cơ quan cấp chứng chỉ sử dụng tên dNSName thay thế.

[...]

Trong một số trường hợp, URI được chỉ định làm địa chỉ IP thay vì tên máy chủ. Trong trường hợp này, đối tượng iPAddress phải có mặt trong chứng chỉ và phải khớp chính xác với IP trong URI.

Điều này có nghĩa là bạn không thể bỏ đi bằng cách đặt địa chỉ IP trong Tên thường dùng (CN) của DN chủ đề trong chứng chỉ máy chủ của bạn. Nếu bạn đang sử dụng địa chỉ IP, nó PHẢI nằm trong mục nhập Tên thay thế chủ đề. (Bắt đầu với Java 7, keytool có các tùy chọn để tạo các chứng chỉ như vậy.)

Bạn sẽ tìm thấy thêm chi tiết về các lệnh để sử dụng trong this answer.

Điều này đang được nói, sử dụng địa chỉ IP chỉ có thể thực sự hoạt động nhiều nhất trong môi trường thử nghiệm. Tôi không nghĩ rằng bất kỳ CA thương mại nào sẽ cung cấp cho bạn chứng chỉ dựa trên địa chỉ IP. Tôi khuyên bạn nên thiết lập các mục DNS (ngay cả khi nó chỉ nằm trong các tệp hosts trong môi trường thử nghiệm).

Thậm chí nếu bạn không sử dụng địa chỉ IP, bạn phải đảm bảo rằng chứng chỉ đó hợp lệ cho tên máy chủ mà bạn đang cố liên hệ với máy chủ: nếu bạn có mục nhập Tên thay thế chủ đề, một trong số đó phải khớp với tên máy chủ; nếu không, tên máy chủ phải nằm trong RDN CN của DN Chủ đề của chứng chỉ này.

Các vấn đề liên quan