找出 JVM 正在使用的金鑰庫。
1. 概述
在使用需要 SSL/TLS 連線或憑證管理的 Java 應用程式時,我們經常需要將憑證匯入 JVM 的金鑰庫。然而,要取得正確的金鑰庫檔案可能很困難,尤其是在使用不同的作業系統和 Java 安裝版本時。
在本教程中,我們將探討多種方法來確定 JVM 正在使用哪個金鑰庫。
2. 使用java_home環境變數
JAVA_HOME環境變數選項提供了尋找 JVM 金鑰庫的最簡單方法。 Java 安裝程式會將此環境變數設定為指向 Java 開發工具包 (JDK) 或 Java 執行時期環境的根目錄。此外,由於 JVM 的預設信任庫 cacerts 始終位於 Java 安裝目錄的標準相對路徑中,因此我們可以使用 JAVA_HOME 快速產生金鑰庫的完整路徑**JAVA_HOME :**
$ echo %JAVA_HOME%\lib\security\cacerts
在這個例子中, JAVA_HOME環境變數指的是 Java 的安裝目錄。 JVM 的預設信任庫檔案 cacerts 位於該安裝路徑的lib/security子資料夾中。
最後,此方法的前提是JAVA_HOME環境變數已正確設定。即使該變數尚未設置,我們也可以設置它,或使用下文所述的其他方法之一。此外,正在執行的程式可能使用的是與JAVA_HOME指向的 Java 版本不同的 Java 安裝,尤其是在安裝了多個 Java 版本的系統上。
3. 尋找使用者特定的金鑰庫
當我們執行 keytool 工具而未指定金鑰庫位置時,Java 會在使用者的主目錄中產生或使用一個金鑰庫。這個使用者特定的金鑰庫與系統的 cacerts 檔案不同,用途也不同。
此外,系統憑證庫 (cacerts) 包含用於驗證來自遠端伺服器的 SSL/TLS 連線所需的受信任憑證授權單位 (CA) 憑證。另外,用戶密鑰庫通常包含用於標識用戶或應用程式的個人私鑰和證書:
$ echo %USERPROFILE%\.keystore
在這個例子中,金鑰庫是使用者特定的,與系統範圍的 cacerts 檔案不同。我們通常用它來儲存個人金鑰和證書,而不是受信任的 CA 證書。此外,我們可能不知道這個預設位置,而且可能會感到疑惑,當我們不提供金鑰庫時,keytool 會將金鑰儲存在哪裡。
4. 使用 Java 系統屬性
金鑰庫位置可以透過 Java 系統特性以程式設計方式決定。這種方法可靠且適應性強,尤其適用於工業應用和自動化系統。
此外,與環境變數(會在 shell 會話或使用者上下文之間變更)不同,Java 系統屬性是執行中的 JVM 實例固有的。這些實例始終反映當前配置:
class KeystoreLocatorIntegrationTest {
private static final Logger logger = LoggerFactory.getLogger(KeystoreLocatorIntegrationTest.class);
@Test
void givenJavaInstallation_whenUsingSystemProperties_thenKeystoreLocationFound() {
String javaHome = System.getProperty("java.home");
String separator = System.getProperty("file.separator");
String cacertsPath = javaHome + separator + "lib" + separator
+ "security" + separator + "cacerts";
assertNotNull(javaHome);
logger.info("Java Home: {}", javaHome);
logger.info("Expected cacerts location: {}", cacertsPath);
File cacertsFile = new File(cacertsPath);
if (cacertsFile.exists()) {
logger.info("Cacerts file exists: YES");
logger.info("Absolute path: {}", cacertsFile.getAbsolutePath());
assertTrue(cacertsFile.exists());
}
String customTrustStore = System.getProperty("javax.net.ssl.trustStore");
if (customTrustStore != null) {
logger.info("Custom trustStore is specified: {}", customTrustStore);
} else {
logger.info("No custom trustStore specified, using default");
}
String userHome = System.getProperty("user.home");
String userKeystore = userHome + separator + ".keystore";
assertNotNull(userHome);
logger.info("User keystore location: {}", userKeystore);
}
}
在這個例子中,我們取得 Java 使用者主目錄並建立 cacerts。此外,我們也會檢查自訂的trustStore屬性,並取得使用者的主金鑰庫位置路徑。此方法利用 Java 系統屬性來尋找金鑰庫。 java.home java.home傳回目前正在執行的 JVM 的 Java 安裝目錄。這可能與JAVA_HOME環境變數不同,尤其是在安裝了多個 Java 版本的系統上。
總之,這種程式化方法在運行時確定密鑰庫位置非常方便。此外,已部署的應用程式環境可能與我們的開發工作站不同。它也是最可靠的方法,因為它使用了與 JVM 用於發現信任庫相同的功能。
5. 結論
本文探討了三種確定 JVM 正在使用的金鑰庫的方法。要找到系統級的 cacerts 文件,我們可以使用JAVA_HOME環境變量,在用戶主目錄中查找預設用戶密鑰庫,或使用 Java 系統屬性以程式設計方式查找。
最後, JAVA_HOME方法速度快,適合手動操作;而程序化方法在運行時確定密鑰庫位置方面更可靠,並且適用於多種情況。了解各種金鑰庫位置對於 Java 程式中有效的憑證管理至關重要。
和往常一樣,程式碼可以在 GitHub 上找到。