2014-11-07 51 views
3

據我瞭解,在大多數情況下,這個例外狀態,證書擁有者CN(公用名稱)不匹配在URL中的主機名稱。然而,在我的情況下,它們匹配,但異常仍然引起..爲什麼我會得到「沒有找到匹配的名稱」CertificateException?

遠程服務器證書層次結構是:用CN=sms.main.ru

  • 證書與第一個和CN=client.sms.main.ru簽署

    1. 自簽名證書

    我的Java客戶端下的apache-tomcat的6推出,並嘗試連接到https://client.sms.main.ru/及以下異常被拋出:

    No name matching client.sms.main.ru found 
    

    兩個證書經由$JAVA_HOME/bin/keytool加入$JAVA_HOME/jre/lib/security/cacerts如在由unixtippse答案示於How do you configure Apache/Tomcat to trust internal Certificate Authorities for server-to-server https requests

    的Java代碼是相當簡單:

    URL url = new URL(strurl); 
    HttpURLConnection con = (HttpURLConnection) url.openConnection(); 
    con.setRequestMethod("GET"); 
    con.setRequestProperty("Connection", "close"); 
    con.setDoOutput(true); 
    con.connect(); 
    

    我缺少什麼?


    有趣的是,當我嘗試在Windows PC上的瀏覽器訪問這個URL,它說,該證書不被信任,我將它添加到瀏覽器的例外列表,它工作正常。所以它看起來像我不正確地將這些證書添加到cacerts,以便Java不能使用它們。但我可以很容易地通過別名或通過CN與找到他們:

    $JAVA_HOME/bin/keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts | less 
    
  • +0

    如果它是自簽名的,那麼它將不會被信任,因爲層次結構不會一直達到TA – 2014-11-07 02:10:41

    +0

    @Scary Wombat但我將它們都添加到'cacerts'.....並在那裏標記爲可信這是不夠的?這不是應該如何讓自簽證書被信任嗎? – horgh 2014-11-07 02:13:11

    +0

    您正在使用錯誤的類訪問https – CharlieS 2014-11-07 02:20:31

    回答

    3

    自簽名的證書在結束所有我需要做的就是:

    1. 禁用主機名驗證:

      // Create all-trusting host name verifier 
      HostnameVerifier allHostsValid = new HostnameVerifier() { 
          public boolean verify(String hostname, SSLSession session) { 
           return true; 
          } 
      }; 
      // Install the all-trusting host verifier 
      HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); 
      
    2. 確保使用默認的cacerts文件,同時研究I tri以禁用ssl證書驗證並使用可在SO上的大量線程(實施自己的X509TrustManager)中找到的代碼,即在Java: Overriding function to disable SSL certificate check中。此代碼替換了我需要的默認SSLSocketFactory。所以我必須刪除所有這些東西,並使用禁用主機名驗證的代碼。

    我離開了HttpURLConnection。無需用HttpsURLConnection替換它。

    當然,如果我設法避免禁用主機名驗證,那肯定會好得多,但我不能。可能是證書出了問題..

    +0

    我會很高興看到對downvoting的任何評論.. – horgh 2015-04-23 02:00:59

    +0

    沒有downvote,但禁用主機名驗證幾乎總是做錯的事情。不應該推薦它作爲解決方案。 – eis 2017-05-08 06:35:47

    -4

    使用的HttpsURLConnectionSSLSocketFactory執行SSL握手。

    +0

    這應該如何幫助我? – horgh 2014-11-07 02:13:44

    +0

    嘗試研究'HttpsURLConnection'。您正在使用錯誤的類來執行SSL,即證書如何呈現給服務器。你的代碼不會對證書做任何事情。如果你使用我建議的類,它會。 – CharlieS 2014-11-07 02:19:18

    +0

    感謝您的評價,不是鼓勵幫助的好方法! – CharlieS 2014-11-07 02:19:37

    1

    這是以前我是怎樣信任在Tomcat

    static private SSLSocketFactory newSslSocketFactory(String jksFile, char[] password) { 
    
        try { 
         KeyStore trusted = KeyStore.getInstance("JKS"); 
         InputStream in = StaticHttpsClient.class.getClassLoader().getResourceAsStream(jksFile); 
         try { 
          trusted.load(in, password); 
         } finally { 
          in.close(); 
         } 
    
         SSLSocketFactory socketFactory = new SSLSocketFactory(trusted); 
         HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; 
         socketFactory .setHostnameVerifier((X509HostnameVerifier) hostnameVerifier); 
         return socketFactory; 
        } catch (Exception e) { 
         throw new AssertionError(e); 
        } 
    } 
    
    static protected ClientConnectionManager createClientConnectionManager(String jksFile, char[] password) { 
        SchemeRegistry registry = new SchemeRegistry(); 
    
        registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory())); 
        registry.register(new Scheme("https", 443, newSslSocketFactory(jksFile, password))); 
        return new SingleClientConnManager(registry); 
    
    } 
    
    +0

    謝謝,但是我設法找到了一個更簡單的解決方案 – horgh 2014-11-07 06:49:26

    相關問題