2016-04-21 150 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和服务器密钥库应主机名称

请建议,如果有更好的解决方案。

相关问题