2011-08-28 208 views
10

我正嘗試使用安全套接字層(HTTPS)與Java中的PHP腳本建立連接,但我已經發現爲確保最大的安全性/有效性,我必須導入SSL證書我的網站用於我的應用程序...我不知道該怎麼做。Java和SSL證書

如果有幫助,我的SSL證書不是自簽名的,而是由StartSSL提供的,我正在使用Eclipse IDE。

有人能指出我正確的方向嗎?即我需要什麼文件,我應該在哪裏導入它們,以及在Java中需要什麼代碼等等?

+0

如果它在沒有導入任何證書的情況下工作,我不會看到如何確保/增加安全性通過導入網站證書。如果必須導入任何證書,則它是StartSSL的根證書,但不是您的網站證書,因爲Java無法將StartSSL識別爲有效的證書頒發機構。 –

+0

@JB哦。這只是因爲在我之前的問題中,chubbard說我應該確保在我的客戶端驗證服務器的證書,以確保我正在與虛假服務對話,並提到了有關keytool的一些信息。因此,如果您說導入網站證書不影響安全性,爲什麼有人會導入SSL證書? – Andy

+1

這是Java的SSL堆棧,它將驗證網站證書,就像瀏覽器一樣。您在訪問之前是否導入了您訪問的所有SSL網站的證書?不是。瀏覽器驗證其證書,因爲它通過瀏覽器知道的知名證書頒發機構的認證。 StartSSL是您的案例中的證書頒發機構。 Java做同樣的事情。您可能需要導入StartSSL的證書,但不需要導入網站證書。 –

回答

24

我發現,要保證最大信號的安全性/有效性我要導入我的網站使用SSL證書到我的應用程序

你是正確的部分,當你作出這樣的聲明。您不需要導入您的SSL證書。導入StartSSL CA證書就足夠了。

此外,沒有將證書導入到Java應用程序中。 Java中的SSL支持依賴於密鑰庫和信任庫的概念,而不是在應用程序中打包的某些證書​​上。如果您要發佈應用程序以供最終用戶下載和執行,則不需要在應用程序中發佈您的證書或私鑰。私鑰和相關證書將存儲在密鑰庫中,只有您可以訪問。

您的應用程序的最終用戶將依賴於Java運行時的SSL支持,這將允許應用程序在驗證服務器證書後建立到站點的SSL連接。 Java運行時會在信任庫中附帶一組默認的CA證書,並且SSL連接成功建立的唯一先決條件是服務器的SSL證書由信任庫中的一個CA頒發。 startssl如果的證書不存在於Java運行時的信任,至少爲6個版本,因此:

  • 你可以指導你的最終用戶執行導入startssl如果CA證書的活動到Java信任庫中。可能有幫助的鏈接包括this StartSSL forum thread(僅需要將前面4個步驟導入CA信任庫到信任庫),a GitHub projectthis blog post;一個免責聲明 - 我沒有嘗試使用任何這些,你應該使用它,風險自負。
  • 或者,你可以使用-Djavax.net.ssl.trustStore=<path_to_truststore> -Djavax.net.ssl.trustStorePassword=<truststore_password> JVM啓動標誌用自己的信任初始化應用程序,或初始化SSL連接之前執行以下代碼:

    System.setProperty("javax.net.ssl.trustStore","<path_to_truststore>"); 
    System.setProperty("javax.net.ssl.trustStorePassword","<truststore_password>"); 
    

    這是唯一的,如果你的應用程序是一個可行的方法Java SE應用程序不會碰巧是一個小程序(或者對指定信任庫的方式有類似限制的應用程序)。


這也將有助於閱讀了Java keytool documentation

+0

謝謝您提供的信息豐富且「富有洞察力」的答案!基本上你在說什麼,是我應該只需要導入StartSSL的CA證書,然後我應該安全下去?如果我是正確的,那麼您提供的鏈接僅適用於最終用戶,並且證書不會與我的軟件一起分發,但第二項要點中的方法意味着StartSSL的CA證書將始終存在,並且我的最終用戶不需要做任何事情?因爲我不想讓我的客戶必須導入StartSSL的CA證書...... – Andy

+0

CA證書有多種用途;對於像Tomcat這樣的可以通過HTTPS爲站點提供站點證書的Java服務器,您需要擁有帶站點證書的密鑰庫,以及帶有StartSSL CA證書的*信任庫。 SSL客戶端(如瀏覽器或Java應用程序)只需在信任庫中擁有StartSSL CA證書(或任何用於驗證信任的證書)。因此,您的最終用戶必須將CA證書導入到cacerts文件中,並且該應用程序所建立的連接將是安全的。 –

+0

......我不知道它是否有所作爲,但我計劃使用launch4j將JRE與我的應用程序一起分發,這樣我就不必依賴我的客戶安裝了Java。那麼,這是否意味着StartSSL的CA證書也可以與JRE一起打包? – Andy

0

看看下面的文章:http://stilius.net/java/java_ssl.php 它包含代碼示例,這可能有助於在您嘗試從代碼訪問您的腳本的情況下。

需要注意的是,你要麼應該使用系統屬性

javax.net.ssl.keyStore 
javax.net.ssl.keyStorePassword 

使用keytool工具SSL證書傳遞到JVM或將其導入到JRE密鑰庫

+0

謝謝你的回答@Sergey。不幸的是,我已經看過你建議的文章。如果我再研究一下它可能會有所幫助,但這對我來說是一個全新的主題,所以我有時會面臨一些壓力,所以我討厭這麼說,但我一直在尋找最簡單的方法。幸運的是,我發現了與Vineet討論的最佳方式,但是非常感謝! – Andy

0

我發現,要保證最大信號安全/有效期我必須 導入SSL證書

不,你沒有。如果您的客戶尚未信任服務器證書的簽署人,則只需要執行此步驟,這僅在服務器證書是自簽名或簽名的情況下才會產生。由內部CA.

+0

謝謝你的回答。不過,不幸的是,我已經導入了一個證書 - 但我不認爲現在有必要,但是我怎麼知道我的客戶是否不信任服務器證書的簽名者:我會收到一個例外應用時使用'Htttpsurlconnection'? – Andy

+0

@你會得到同樣的例外,你在第一個地方。我的代碼中的 – EJP

1

以下方法加載默認(cacerts)密鑰庫,檢查是否安裝了證書,如果沒有,則安裝它。它消除了在任何服務器上手動運行keystore命令的需要。

它假設默認密鑰庫密碼(changeit)未更改,如果不是,則更新CACERTS_PASSWORD。請注意,該方法在添加證書後保存密鑰庫,因此在證書永久存儲在商店後運行後。

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.cert.Certificate; 
import java.security.cert.CertificateException; 
import java.security.cert.CertificateFactory; 

/** 
* Add a certificate to the cacerts keystore if it's not already included 
*/ 
public class SslUtil { 
    private static final String CACERTS_PATH = "/lib/security/cacerts"; 

    // NOTE: DO NOT STORE PASSWORDS IN PLAIN TEXT CODE, LOAD AT RUNTIME FROM A SECURE CONFIG 
    // DEFAULT CACERTS PASSWORD IS PROVIDED HERE AS A QUICK, NOT-FOR-PRODUCTION WORKING EXAMPLE 
    // ALSO, CHANGE THE DEFAULT CACERTS PASSWORD, AS IT IMPLORES YOU TO! 
    private static final String CACERTS_PASSWORD = "changeit"; 

    /** 
    * Add a certificate to the cacerts keystore if it's not already included 
    * 
    * @param alias The alias for the certificate, if added 
    * @param certInputStream The certificate input stream 
    * @throws KeyStoreException 
    * @throws NoSuchAlgorithmException 
    * @throws CertificateException 
    * @throws IOException 
    */ 
    public static void ensureSslCertIsInKeystore(String alias, InputStream certInputStream) 
      throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{ 
     //get default cacerts file 
     final File cacertsFile = new File(System.getProperty("java.home") + CACERTS_PATH); 
     if (!cacertsFile.exists()) { 
      throw new FileNotFoundException(cacertsFile.getAbsolutePath()); 
     } 

     //load cacerts keystore 
     FileInputStream cacertsIs = new FileInputStream(cacertsFile); 
     final KeyStore cacerts = KeyStore.getInstance(KeyStore.getDefaultType()); 
     cacerts.load(cacertsIs, CACERTS_PASSWORD.toCharArray()); 
     cacertsIs.close(); 

     //load certificate from input stream 
     final CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
     final Certificate cert = cf.generateCertificate(certInputStream); 
     certInputStream.close(); 

     //check if cacerts contains the certificate 
     if (cacerts.getCertificateAlias(cert) == null) { 
      //cacerts doesn't contain the certificate, add it 
      cacerts.setCertificateEntry(alias, cert); 
      //write the updated cacerts keystore 
      FileOutputStream cacertsOs = new FileOutputStream(cacertsFile); 
      cacerts.store(cacertsOs, CACERTS_PASSWORD.toCharArray()); 
      cacertsOs.close(); 
     } 
    } 
} 

使用它,像這樣:

SslUtil.ensureSslCertIsInKeystore("startssl", new FileInputStream("/path/to/cert.crt")); 
+0

這導致java.io.FileNotFoundException:C:\ Program Files文件(x86)\ Java \ jre1.8.0_45 \ lib \ security \ cacerts(訪問被拒絕)我將證書下載到臨時文件夾,然後用一個唯一的別名(不是starttls)和fileInputStream導入它。我的證書來自HTTPS服務器(www.gmx.at) – lumo

+0

謝謝!這篇文章幫助我閱讀一個密鑰庫。 – rray

+0

問題,在代碼中以純文本形式存儲密碼不是一個相當大的安全漏洞嗎?或者,當涉及SSL連接時,這並不重要嗎? – Flaom

2

顯然,由於某種原因,mailgun工程師不希望給我們如何解決這個明確的指示。這就是我所做的

我們運行tomcat8並通過球衣web服務連接到mailgun API。我遵循這個用戶指示,它工作正常。希望這可以幫助某人。

1/22,由於賽門鐵克的PKI基礎設施設置爲不可信,我們更新了SSL證書。某些舊版本的Java沒有「DigiCert Global Root G2」CA.

有幾種選擇:

導入 「DigiCert全局根G2」 CA到您 「的cacerts」 文件。 將您的JRE升級到8u91(或更高版本),其中包含此根目錄。 要導入「DigiCert Global Root G2」您可以從https://www.digicert.com/digicert-root-certificates.htm下載根目錄。確保您正在下載正確的根證書。

一旦證書下載後,您需要將它與類似如下的命令導入:

的keytool -import -keystore -trustcacerts /路徑/到/ cacerts的-storepass的changeit -noprompt -alias digicert -global-root -g2 -file /path/to/digicert.crt 您需要設置Java密鑰庫的路徑以及下載的根證書的位置。


所以 1. /path/to/digicert.crt是您剛剛下載的文件。 2。/ path/to/cacerts - 這是你的JRE路徑。我找到/ -name cacerts -print「這將幫助您快速找到文件系統上的所有java cacerts。對我來說,它是/ usr/lib/jvm/java-7 -openjdk-amd64/jre/lib/security/cacerts