将 JRE 设置为使用 Windows 信任库,特别是用户的信任库

Set JRE to use Windows trust store, specifically the user's trust store

摘要:Java 选项 -Djavax.net.ssl.trustStoreType=WINDOWS-ROOT 允许 Java 使用 计算机帐户的 Windows 信任库。 什么选项允许它为 用户帐户?

使用 Windows 信任库

我们在 Windows 客户端上 运行 有一个 Java 应用程序。该应用程序从各种来源获取数据,其中一些来源使用不在默认 cacerts 文件中的证书。

当用户选择访问外部数据的项目时,系统会提示他们下载外部站点的证书。由于我们的安全设置,cacerts 文件对用户是只读的。因为 JRE 无法将证书导入 cacerts,所以不会下载外部证书。并且一遍又一遍地提示用户下载证书。

当用户获得 cacerts 的写入权限时,问题就不会发生。但是我们的安全团队不允许我们向普通用户授予对该文件的写入权限。他们的政策是 C: 驱动器上的任何文件,在用户自己的配置文件之外,都不应是可读写的。

我们认为我们找到了使 Java 使用 Windows 信任库的解决方法。我们将标志 -Djavax.net.ssl.trustStoreType=WINDOWS-ROOT 添加到启动脚本。这迫使 Java 使用用户可以写入的 Windows 信任库。

不幸的是,用户只能写入他们的证书存储区,而不能写入计算机的证书存储区。当我们以管理员身份 运行 应用程序时,证书将导入到计算机的商店中。之后,不会提示普通用户下载证书。但是,如果我们不 运行 它一次具有管理员权限,则不会导入证书,因为 Java 尝试写入 Windows 计算机帐户 商店,与 cacerts.

一样严格锁定

是否有标志强制 Java 使用整个 Windows 信任库,而不仅仅是计算机帐户的存储?

JSSE Reference Guide 回答了您的问题。

In this case, if such a property exists but the file it specifies does not, then no truststore is used. If no javax.net.ssl.trustStore property exists, then a default truststore is searched for. If a truststore named java-home/lib/security/jssecacerts is found, it is used. If not, then a truststore named java-home/lib/security/cacerts is searched for and used (if it exists).

如果您没有权限覆盖这两个文件 jssecacerts 或 cacerts 之一,那么您的问题的答案是否定的。

Windows-ROOT 类型的密钥库应该可以工作 -- 它应该访问 TrustedRootCAs 部分(MMC/certmgr.msc 中的行,[=31 中的选项卡=]) 当前用户的商店。在我的系统上,最大为 UAC 的 8.1 Home,但不在域或工作组中并且没有策略更改(至少 none 我授权),Java 代码能够插入 Windows-ROOT -- 但它确实会弹出一个关于 "Warning: about to install CA cert blah blah this may be a security risk blah blah" 的对话框,我必须点击它;如果该进程无法访问 'workstation' (显示),我不知道会发生什么,如果它失败,我也不会感到惊讶。使用我的普通 ID (local,admin) 和 Guest (local,peon) 进行确认;作为一个独立的系统,我没有真正的计算机帐户,只有 'local machine' 哪个 IINM 实际上是本地系统,并且插入不在那里。

您可以尝试 Windows-MY,这对我来说应该(再次)访问当前用户的商店个人部分;对我来说,在没有上述对话框的情况下也能工作。 Personal 打算用于带有私钥的证书,可用于向服务器或收件人验证this machine/user,并且其中有一个 cert-only 用于信任另一个系统可能会使您的知识渊博的用户感到困惑甚至惊慌,但它确实对我有用。

除了 javax.net.ssl.trustStoreType=Windows-ROOT 我还必须定义 javax.net.ssl.trustStore=NUL 才能在 Windows 上工作,即使 println(System.getProperty('javax.net.ssl.trustStore')) 打印了 null。另见 https://newbedev.com/import-windows-certificates-to-java

因为 Gradle 我需要这个,所以我必须将以下内容添加到我的 gradle.properties:

systemProp.javax.net.ssl.trustStore=NUL
systemProp.javax.net.ssl.trustStoreType=Windows-ROOT

在 运行 Gradle 一次使用此配置后,我不再需要 systemProp.javax.net.ssl.trustStore=NUL,直到我添加了另一个 Maven 存储库。然后我又得到了一个PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

似乎Gradle在某个地方缓存了这个证书,因为删除了我用户家的.gradle目录后,我还需要systemProp.javax.net.ssl.trustStore=NUL。所以最好把它留在那里。