2016-04-21 358 views
1

我正在對使用自簽名證書的SSL雙向認證。 我已經創建了兩個密鑰庫客戶端(客戶keystore.jks)中,服務器端(server-keystore.jks)中,,從密鑰庫並導入客戶端證書到服務器的密鑰存儲和服務器證書到客戶端密鑰庫都導出的證書。並在server.xml中更新了所需的連接器條目,將兩個證書添加到java信任存儲區cacerts面對javax.net.ssl.SSLHandshakeException:實施SSL雙向認證時收到致命警報:bad_certificate問題

Java客戶端代碼:

KeyStore trustStore = KeyStore.getInstance("JKS", "SUN"); 
      trustStore.load(SSLImplemetation.class.getResourceAsStream("C:/Program Files/Java/jdk1.7.0_79/jre/lib/security/cacerts"), "changeit".toCharArray()); 
      String alg = KeyManagerFactory.getDefaultAlgorithm(); 
      TrustManagerFactory fac = TrustManagerFactory.getInstance(alg); 
      fac.init(trustStore); 


      KeyStore keystore = KeyStore.getInstance("JKS", "SUN"); 
      keystore.load(SSLImplemetation.class.getResourceAsStream("<dir path>/client-keystore.jks"), "test".toCharArra()); 
      String keyAlg = KeyManagerFactory.getDefaultAlgorithm(); 
      KeyManagerFactory keyFac = KeyManagerFactory.getInstance(keyAlg); 
      keyFac.init(keystore, "test".toCharArray()); 

       SSLContext ctx = SSLContext.getInstance("TLS", "SunJSSE"); 
      ctx.init(keyFac.getKeyManagers(),fac.getTrustManagers(), new SecureRandom()); 

      SslContextedSecureProtocolSocketFactory secureProtocolSocketFactory = new SslContextedSecureProtocolSocketFactory(ctx); 
      Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) secureProtocolSocketFactory, 8443)); 

      CloseableHttpClient httpClient = HttpClientBuilder.create().build(); 
      HttpPost request = new HttpPost("<rest service url>"); 

JSONObject obj = new JSONObject(); 
StringEntity params =new StringEntity(obj.toString()); 

    request.addHeader("content-type", "application/json"); 
    request.setEntity(params); 
    HttpResponse response = httpClient.execute(request); 
    System.out.println(response.getStatusLine()); 

的server.xml:

<Connector 
     protocol="org.apache.coyote.http11.Http11Protocol" 
     port="8443" maxThreads="200" scheme="https" secure="true" SSLEnabled="true" 
      clientAuth="true" sslProtocol="TLS" 
      keystoreFile="<dir path>/server-keystore.jks" keystorePass="test" 
      truststoreFile="C:/Program Files/Java/jdk1.7.0_79/jre/lib/security/cacerts" 
      truststorePass="changeit" /> 

我是新來的SS1,所以有點疑惑。 任何幫助,將不勝感激。

回答

0

下面的代碼適用於我,在創建兩個客戶端和服務器密鑰庫並將兩個證書都放入java truststore之後,我已經使用以下代碼進行SSL相互身份驗證。

static final private String KEY_STORE = "D:/sslcertificates/client-keystore.jks"; 
    static final private String KEY_STORE_TYPE = "JKS"; 
    static final private String KEY_STORE_PASS = "test"; 

     public static void main(String[] args) throws JSONException{ 

      try { 
       URL url = new URL("<rest service url>"); 
       HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); 

conn.setHostnameVerifier(新的HostnameVerifier(){

    public boolean verify(String hostname, 
              javax.net.ssl.SSLSession sslSession) { 
         if (hostname.equals("<hostname>")) { 
          return true; 
         } 
         return false; 
        } 
       }); 


       conn.setDoOutput(true); 
       conn.setRequestMethod("POST"); 
       conn.setRequestProperty("Content-Type", "application/json"); 
       try 
       { 
       KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509","SunJSSE"); 
       KeyStore ks = KeyStore.getInstance(KEY_STORE_TYPE); 
       File cert = new File(KEY_STORE); 
       InputStream stream = new FileInputStream(cert); 
       ks.load(stream, KEY_STORE_PASS.toCharArray()); 
       stream.close(); 
       kmf.init(ks,KEY_STORE_PASS.toCharArray()); 

       SSLContext context = SSLContext.getInstance("TLS"); 
       context.init(kmf.getKeyManagers(),null, new SecureRandom());    
       SSLSocketFactory factory = context.getSocketFactory();    
       conn.setSSLSocketFactory(factory); 

       } 
       catch(Exception e) 
       { 
        System.out.println(e); 
       } 

      JSONObject obj = new JSONObject(); 
      obj.put("id","abc"); 
      obj.put("name","surya"); 
      obj.put("domain","IT");  
      String input=obj.toString(); 

     //send request to server....    

      OutputStream os = conn.getOutputStream(); 
      os.write(input.getBytes()); 
      os.flush(); 
      BufferedReader br = new BufferedReader(new InputStreamReader(
        (conn.getInputStream()))); 

      String output; 
      System.out.println("Output from Server .... \n"); 
      while ((output = br.readLine()) != null) { 
       System.out.println(output); 
      } 
      System.out.println("Response code: "+conn.getResponseCode()); 
       System.out.println("Response message: "+conn.getResponseMessage()); 
      conn.disconnect(); 

      } catch (MalformedURLException e) { 

      e.printStackTrace(); 

      } catch (IOException e) { 

      e.printStackTrace(); 

     } 

     } 

server.xml中

<Connector 
    protocol="org.apache.coyote.http11.Http11Protocol" 
    port="8443" maxThreads="200" scheme="https" secure="true" SSLEnabled="true" 
    clientAuth="true" sslProtocol="TLS" 
    keystoreFile="<dir path>/server-keystore.jks" keystorePass="test"/> 

注意:設置的HostnameVerifier在HttpsURLConnection的對象和客戶端的CN和服務器密鑰庫應主機名稱

請建議,如果有更好的解決方案。

相關問題