2013-06-12 22 views
7

Tôi đang cố gắng để thực hiện một cuộc gọi đến REST API, nhưng tôi nhận được ngoại lệ sau đây (Hoàn StackTrace ở cuối):Tôi làm cách nào để tắt xác minh SSL?

"javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target" 

Tôi hỏi nhà cung cấp API về vấn đề này và nói rằng có cái gì đó sai với thư viện SSL mà bạn đang sử dụng.

Bạn giải quyết vấn đề này như thế nào? Với cùng mã này (bên dưới), tôi đã thực hiện các lệnh gọi tới REST API NIMBLE mà không có vấn đề gì, nhưng trong trường hợp này nó không hoạt động. Sau đó, tôi không có bất kỳ tệp nào (.cer).

Tôi cần hủy kích hoạt xác minh SSL vì phương thức bảo mật là khóa API mà tôi đã có.

Mọi đề xuất?

Cảm ơn bạn rất nhiều!

==== Console: ====

POST https://api.nexalogy.com/project/create?api_key=XXXXXXXXXXXXXXXXXXXX 
HTTP Header:"Content-Type" "application/json" 
HTTP Body:[{"name":"project1","lang":"en","type":"twitter"}] 
api_key:XXXXXXXXXXXXXXXXXXXX 
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 

Tôi cũng đã thử các hình thức sau đây và ngoại lệ là như nhau:

POST https://api.nexalogy.com/project/create 
HTTP Header:"Content-Type" "application/json" 
HTTP Header:"api_key" "XXXXXXXXXXXXXXXXXXXX" 
HTTP Body:[{"name":"project1","lang":"en","type":"twitter"}] 
api_key:XXXXXXXXXXXXXXXXXXXX 
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 

==== Mã: == ==

package servlet; 

import java.io.BufferedReader; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import javax.servlet.ServletException; 
import javax.servlet.annotation.WebServlet; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

@WebServlet("/AddProject") 
public class AddProject extends HttpServlet { 
    private static final long serialVersionUID = 1L; 
    public AddProject() { 
    } 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    } 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     String body="[{\"name\":\"project1\",\"lang\":\"en\",\"type\":\"twitter\"}]"; 
     String api_key="XXXXXXXXXXXXXXXXXXXX"; 
     String str_response=""; 
     String line=""; 
     URL url = new URL("https://api.nexalogy.com/project/create?api_key="+api_key); 
     try{ 
      HttpURLConnection connection = (HttpURLConnection)url.openConnection(); 
      connection.setRequestMethod("POST"); 
      connection.setRequestProperty("Content-Type","application/json"); 
      System.out.println("POST https://api.nexalogy.com/project/create?api_key="+api_key); 
      System.out.println("HTTP Header:"+"\"Content-Type\" \"application/json\""); 
      System.out.println("HTTP Body:"+body); 
      System.out.println("api_key:"+api_key); 
      connection.setUseCaches(false); 
      connection.setDoInput(true); 
      connection.setDoOutput(true); 
      DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); 
      wr.writeBytes(body); 
      wr.flush(); 
      wr.close(); 
      InputStream is = connection.getInputStream(); 
      InputStreamReader isr = new InputStreamReader(is); 
      BufferedReader rd = new BufferedReader(isr); 
      while ((line = rd.readLine()) != null) str_response+= line + '\r'; 
      rd.close(); 
      System.out.println("str_response:"+str_response); 
     }catch(Exception e){ 
      e.printStackTrace(System.out); 
      //throw new RuntimeException(e); 
     } 
    } 
} 

==== StackTrace Complete: ====

com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:131) 
    at com.sun.jersey.api.client.Client.handle(Client.java:616) 
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:559) 
    at com.sun.jersey.api.client.WebResource.post(WebResource.java:230) 
    at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.tREST_2Process(Twitter_api_create_project.java:955) 
    at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.tJava_1Process(Twitter_api_create_project.java:635) 
    at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.runJobInTOS(Twitter_api_create_project.java:1641) 
    at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.main(Twitter_api_create_project.java:1494) 
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source) 
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source) 
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source) 
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source) 
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source) 
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler$1$1.getOutputStream(URLConnectionClientHandler.java:203) 
    at com.sun.jersey.api.client.CommittingOutputStream.commitWrite(CommittingOutputStream.java:117) 
    at com.sun.jersey.api.client.CommittingOutputStream.write(CommittingOutputStream.java:89) 
    at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source) 
    at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source) 
    at sun.nio.cs.StreamEncoder.implFlush(Unknown Source) 
    at sun.nio.cs.StreamEncoder.flush(Unknown Source) 
    at java.io.OutputStreamWriter.flush(Unknown Source) 
    at java.io.BufferedWriter.flush(Unknown Source) 
    at com.sun.jersey.core.util.ReaderWriter.writeToAsString(ReaderWriter.java:191) 
    at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.writeToAsString(AbstractMessageReaderWriterProvider.java:128) 
    at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:88) 
    at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:58) 
    at com.sun.jersey.api.client.TerminatingClientHandler.writeRequestEntity(TerminatingClientHandler.java:305) 
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler._invoke(URLConnectionClientHandler.java:182) 
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:129) 
    ... 7 more 
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 
    at sun.security.validator.PKIXValidator.doBuild(Unknown Source) 
    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source) 
    at sun.security.validator.Validator.validate(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source) 
    ... 35 more 
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source) 
    at java.security.cert.CertPathBuilder.build(Unknown Source) 
    ... 41 more 

EDITED 2013/06/13 Giải pháp: thực hiện X509TrustManager

Thêm mã sau đây ...

HttpsURLConnection connection = (HttpsURLConnection)url.openConnection(); 
connection.setRequestMethod("POST"); 
connection.setUseCaches(false); 
connection.setDoInput(true); 
connection.setDoOutput(true); 
if (connection instanceof HttpsURLConnection) { 
    try { 
     KeyManager[] km = null; 
     TrustManager[] tm = {new RelaxedX509TrustManager()}; 
     SSLContext sslContext = SSLContext.getInstance("SSL"); 
     sslContext.init(null, tm, new java.security.SecureRandom()); 
     SSLSocketFactory sf = sslContext.getSocketFactory(); 
     ((HttpsURLConnection)connection).setSSLSocketFactory(sf); 
     System.out.println("setSSLSocketFactory OK!"); 
    }catch (java.security.GeneralSecurityException e) { 
     System.out.println("GeneralSecurityException: "+e.getMessage()); 
    } 
} 

... và thêm các lớp sau (thực hiện X509TrustManager)

class RelaxedX509TrustManager implements X509TrustManager { 
    public boolean isClientTrusted(java.security.cert.X509Certificate[] chain){ return true; } 
    public boolean isServerTrusted(java.security.cert.X509Certificate[] chain){ return true; } 
    public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } 
    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String input) {} 
    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String input) {} 
} 
+0

những phiên bản của Java bạn đang sử dụng.? – Bruno

+0

Hi, nhờ bạn trả lời, tôi thấy nhận xét của bạn, tôi đã sử dụng java6, bây giờ tôi cài đặt và cấu hình java7 nhưng lỗi vẫn là như nhau:/ tôi sẽ phải cố gắng lựa chọn thứ hai bạn đề cập đến. –

+0

tôi phải thực hiện "X509TrustManager" Interface (http://docs.oracle.com/javase/6/docs/api/javax/net/ssl/X509TrustManager.html), và nâng cấp lên java7, hai điều này là giải pháp, bây giờ làm việc tốt. Cảm ơn! –

Trả lời

7

Hãy thử điều này

public void disableCertificates() { 
    TrustManager[] trustAllCerts = new TrustManager[]{ 
     new X509TrustManager() { 

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

      @Override 
      public void checkClientTrusted(
        java.security.cert.X509Certificate[] certs, String authType) { 
      } 

      @Override 
      public void checkServerTrusted(
        java.security.cert.X509Certificate[] certs, String authType) { 
      } 
     } 
    }; 

    // Install the all-trusting trust manager 
    try { 
     SSLContext sc = SSLContext.getInstance("SSL"); 
     sc.init(null, trustAllCerts, new java.security.SecureRandom()); 
     HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
    } catch (Exception e) { 
    } 
} 
+4

Vui lòng không sử dụng mã này trong môi trường sản xuất vì nó vô hiệu hóa tất cả kiểm tra chứng chỉ. Do đó, việc triển khai của bạn sẽ dễ bị tấn công [MITM attack] (http://en.wikipedia.org/wiki/Man-in-the-middle_attack). –

+1

Xin chào! cảm ơn bạn đã trả lời, tôi đã thử với mã này, nhập javax.net.ssl.TrustManager và javax.net.ssl.X509TrustManager, và tôi gọi phương thức này trước mã của tôi, nhưng ngoại lệ vẫn nói như vậy. –

+1

Xin vui lòng không sử dụng mã này * ở tất cả. * Không có điểm trong việc triển khai một giải pháp không an toàn thậm chí chỉ để kiểm tra nó. Bạn đang chạy nguy cơ bị “rò rỉ” vào sản xuất, đó sẽ là một vi phạm bảo mật * lớn *. Ngoài ra, mã bỏ qua các ngoại lệ và vi phạm hợp đồng 'TrustManager.' Tránh. – EJP

-2

Vui lòng sử dụng chứng chỉ với chuỗi chứng chỉ hoàn chỉnh. Điều này có nghĩa là cần ít nhất chứng chỉ gốc.

Bạn chỉ nhập chứng chỉ kết thúc của đối tác và việc triển khai không thể xác minh chuỗi chứng chỉ. Ít nhất là chứng chỉ gốc là cần thiết.

+0

Điều đó không đúng. Tất cả những gì cần thiết là * bất kỳ * giấy chứng nhận người ký nào, được nhập là 'đáng tin cậy'. Thông thường, giá trị cao nhất được nhập. Đồng đẳng nên gửi phần còn lại của chuỗi cùng với chứng chỉ của nó. – EJP

+0

@EJP Tôi đã viết rằng ít nhất chứng chỉ gốc là cần thiết (trong đoạn đầu tiên). Tôi đã sửa đoạn thứ hai để làm rõ điều này. –

3

Tôi cần hủy kích hoạt xác minh SSL vì phương thức bảo mật là KEY API mà tôi đã có.

Không rõ cách bạn nghĩ khóa API (và khía cạnh bảo mật mà nó cung cấp) có liên quan đến bảo mật do SSL/TLS cung cấp: chắc chắn không giải quyết được các khía cạnh bảo mật giống nhau. SSL/TLS là về việc bảo vệ việc truyền dữ liệu từ việc nghe lén và thay đổi.

Nếu bạn kiểm tra máy chủ bạn đang cố gắng liên hệ với this SSL testing service, bạn sẽ thấy máy chủ yêu cầu máy khách hỗ trợ chỉ dẫn tên máy chủ (SNI): máy chủ lưu trữ nhiều máy chủ với các chứng chỉ khác nhau.

Nếu khách hàng của bạn không hỗ trợ SNI (Java chỉ hỗ trợ nó ở phía máy khách từ phiên bản 7), yêu cầu sẽ được trình bày với chứng chỉ khác với chứng chỉ thụt vào: nó có thể thất bại hoặc xác minh chứng chỉ hoặc máy chủ thủ tục xác minh tên. Vô hiệu hóa một trong hai kiểm tra làm cho kết nối dễ bị tấn công Man-In-The-Middle.

  • Tôi muốn nói nguyên nhân gây ra sự cố bạn đang gặp nhất là bạn đang sử dụng phiên bản Java không hỗ trợ SNI (ví dụ: Java 6).

  • Nó cũng có thể là JRE bạn đang sử dụng không có CA đặc biệt này trong cửa hàng tin cậy mặc định của nó. Bạn có thể thử chuyển đổi danh sách chứng chỉ CA mà bạn sẵn lòng tin tưởng từ một nguồn khác (ví dụ: gói Mozilla, thường được đề xuất với cURL). Bạn có thể cần phải hiểu chứng chỉ CA nào là đầu tiên.

    Khi JSSE reference guide says:

    LƯU Ý QUAN TRỌNG: Các tàu với một số lượng hạn chế đáng tin cậy chứng chỉ gốc trong thư mục/lib/security/cacerts tập JDK. Như tài liệu trong keytool, đó là trách nhiệm của bạn để duy trì (có nghĩa là, Add/Remove) Giấy chứng nhận chứa trong tập tin này nếu bạn sử dụng tập tin này như một truststore.

    Tùy thuộc vào cấu hình chứng chỉ của máy chủ bạn liên hệ, bạn có thể cần phải thêm chứng chỉ gốc bổ sung. Nhận được chứng chỉ gốc cụ thể cần thiết từ nhà cung cấp thích hợp.

Bằng cách nào đó: hủy kích hoạt xác minh SSL không phải là giải pháp cho vấn đề của bạn.

EDIT:

Dường như các dịch vụ mà bạn đang cố gắng sử dụng có giấy chứng nhận do StartSSL, mà không phải là một trong những CA kèm theo mặc định với Oracle JRE rõ ràng.

Bạn cần phải download it from StartSSL (hoặc xuất nó từ gói đáng tin cậy mà bạn đã có, nó được gọi là "StartCom ...") và nhập nó vào cửa hàng cacerts với keytool (hoặc cửa hàng tin cậy khác nếu bạn đang sử dụng một chương trình khác):

keytool -import -keystore /path/to/jre/lib/security/cacerts -alias startssl -file startssl.crt 

(Chỉnh sửa lại đường dẫn và tên của file chứng chỉ startssl theo yêu cầu, tất nhiên)