2016-05-16 31 views
2

Ich bin sehr neu in dieser SSL und Zertifikate. Ich habe eine JKS-Datei, die aus einigen Zertifikaten besteht, die Server vertrauen. Ich versuche, alle Zertifikate aus der JKS-Datei zu lesen und es an die getAcceptedIssuers() -Methode zurückzugeben. Die Zertifikate sind vom Typ X509Certificate. Die Methode, die ich implementiert habe, liest die JKS-Datei ordnungsgemäß und erstellt eine Arraylist von X509Certificate-Zertifikaten. Als nächstes, wenn ich versuche, das Arraylist-Array zu konvertieren, bekomme ich diese AusnahmeFehler [Ljava.lang.Object; kann nicht in [Ljava.security.cert.X509Certificate umgewandelt werden, wenn eine Arraylist von X509Certificate in Array konvertiert wird

[Ljava.lang.Object; cannot be cast to [Ljava.security.cert.X509Certificate; 
    at com.sample.ssl.GetCertificates.loadCertificatesFromCompanJks(GetCertificates.java:125) 
    at com.sample.ssl.GetCertificates$1.getAcceptedIssuers(GetCertificates.java:44) 
    at sun.security.ssl.AbstractTrustManagerWrapper.checkAlgorithmConstraints(Unknown Source) 
    at sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(Unknown Source) 
    at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(Unknown Source) 
    at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source) 
    at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source) 
    at sun.security.ssl.Handshaker.processLoop(Unknown Source) 
    at sun.security.ssl.Handshaker.process_record(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.getSession(Unknown Source) 
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:91) 
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:397) 
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:148) 
    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149) 
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121) 
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:573) 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:425) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732) 
    at com.sample.ssl.GetCertificates.postMessage(GetCertificates.java:82) 
    at com.sample.ssl.GetCertificates.main(GetCertificates.java:138) 

Mein Code ist wie folgt

public class GetCertificates { 
    static private TrustManager[] trustmgr = new TrustManager[]{new X509TrustManager() { 

     private X509Certificate[] certs = null; 

     public void checkClientTrusted(X509Certificate[] certs, String authType) { 
      System.out.println("checkClientTrusted"); 
     } 

     public void checkServerTrusted(X509Certificate[] certs, String authType) { 
      System.out.println("checkServerTrusted"); 
     } 

     public X509Certificate[] getAcceptedIssuers() { 
      System.out.println("getAcceptedIssuers"); 
      certs = loadCertificatesFromCompanJks("C:/Users/vinod/Desktop/keystore.jks", "mypassword"); 
      // return new 
      // X509Certificate[]{}; 
      return certs; 
     } 
    }}; 

    public void postMessage() { 
     try { 
      // here I prepare Url to execute and make a call 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

    public static X509Certificate[] loadCertificatesFromCompanJks(String jksPath, String keyStorePassword) { 
     try { 
      X509Certificate X509Certificate[] = null; 
      Certificate[] certs = null; 

      ArrayList<X509Certificate> serverCerts = new ArrayList<X509Certificate>(); 
      FileInputStream is = new FileInputStream(jksPath); 
      KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); 
      String password = keyStorePassword; 
      keystore.load(is, password.toCharArray()); 

      Enumeration e = keystore.aliases(); 
      for (; e.hasMoreElements();) { 

       String alias = (String) e.nextElement(); 
       Certificate cert = keystore.getCertificate(alias); 
       X509Certificate cert1 = (X509Certificate) cert; 
       serverCerts.add(cert1); 
      } 
      is.close(); 
      System.out.println("Number of server certificates : " + serverCerts.size()); 
      X509Certificate = (java.security.cert.X509Certificate[]) serverCerts.toArray(); 
      return X509Certificate; 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public static void main(String[] args) { 
     new GetCertificates().postMessage(); 
    } 
} 

Antwort

3

Ihr Fehler ist hier zu X509Certificate gewirkt:

X509Certificate = (java.security.cert.X509Certificate[]) serverCerts.toArray(); 

Das Überlastung von toArray() eine Object[] und ein Object[] kann nicht auf einem anderen Array wird wieder gegossen werden Art.

ändern, die auf diese Linie:

X509Certificate = serverCerts.toArray(new X509Certificate[serverCerts.size()]); 

Hier werden Sie das Array von der richtigen Art und Größe Zuteilung und es toArray Übergang von der Liste zu füllen.

(Sie können diese schreiben ...

X509Certificate = serverCerts.toArray(new X509Certificate[0]); 

... aber das wird in einer unnötigen Zuordnung zur Folge hat. Bitte lesen Sie die javadocs für toArray(...) für ein besseres Verständnis. (Zugegeben, die Kosten für die zusätzliche Zuteilung ist klein, und man konnte es vermeiden, indem eine vorab zugewiesene/Shared Größe Null Array übergeben.))


Während Sie gerade dabei sind, Ihre Variablennamen ändern, um die Java-Stil Konventionen anzupassen. Es ist furchtbar verwirrend, denselben Bezeichner für einen Typ und eine Variable in derselben Codezeile zu verwenden!

+0

Dank @Stephen sein. Diese Linie funktionierte wie Charme. – user2703788

0

Änderung

 X509Certificate = (java.security.cert.X509Certificate[]) serverCerts.toArray(); 

zu

 X509Certificate = serverCerts.toArray(new java.security.cert.X509Certificate[0]); 

weil toArray return Object [], das nicht b e umwandeln kann zu X509Certificate [] sogar jedes Element von Array

0

Was Sie werfen möchten, sind die Elemente des Arrays und nicht das Array selbst, und deshalb schlägt das Casting fehl. Wenn Sie ein toArray aus einer Liste ausführen, ohne den Typ anzugeben, erhalten Sie ein Array von Object, und obwohl die Objekte vom Typ X509Certificate sind und Sie jede davon einzeln aktualisieren können, können Sie das Array nicht selbst darstellen. Wenn Sie versuchen, das zu tun, werden Sie auf diese Ausnahme stoßen. Ihre Liste muss in ein Array von Elementen des Typs X509Certificate konvertiert werden.

Als Alternative in Java 8, dies zu tun:

X509Certificate[] x509Certificates = serverCerts.parallelStream().toArray(X509Certificate[]::new); 

Ich würde auch Camelcase-Schreibweise, wann immer möglich zu halten vorschlagen, mit. Sie verwenden Großbuchstaben als ersten Buchstaben Ihres Variablennamens.Es sollte auch aussagekräftiger sein, da Sie ein Array von Zertifikaten zurückgeben und nicht nur eines. Diese

:

X509Certificate sollte so etwas wie dieses x509Certificates