您可以使用 X509TrustManager 实现此功能。
获取 SSLContext
SSLContext ctx = SSLContext.getInstance("TLS");
然后使用 SSLContext#init 使用您的自定义对其进行初始化。SecureRandom 和 KeyManager[] 可能为 null。后者仅在执行客户端身份验证时才有用,如果在您的方案中只有服务器需要进行身份验证,则无需设置它。X509TrustManager
从这个SSLContext,使用SSLContext#getSocketFactory获取你的SSSocketFactory,并按计划进行。
至于您的 X509TrustManager 实现,它可能如下所示:
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
//do nothing, you're the client
}
public X509Certificate[] getAcceptedIssuers() {
//also only relevant for servers
}
public void checkServerTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
/* chain[chain.length -1] is the candidate for the
* root certificate.
* Look it up to see whether it's in your list.
* If not, ask the user for permission to add it.
* If not granted, reject.
* Validate the chain using CertPathValidator and
* your list of trusted roots.
*/
}
};
编辑:
Ryan是对的,我忘了解释如何将新根添加到现有根中。让我们假设您当前的可信根的 KeyStore 派生自(JDK 附带的“Java 默认信任存储”,位于 jre/lib/security 下)。我假设你用KeyStore#load(InputStream,char[])加载了该密钥存储(它是JKS格式的)。cacerts
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream in = new FileInputStream("<path to cacerts"");
ks.load(in, "changeit".toCharArray);
默认密码是“changeit”,如果你还没有改变它,好吧,改变它。cacerts
然后,您可以使用 KeyStore#setEntry 添加其他受信任的根。您可以省略保护参数(即 null),KeyStore.Entry 将是一个 TrustedCertificateEntry,它将新的根作为其构造函数的参数。
KeyStore.Entry newEntry = new KeyStore.TrustedCertificateEntry(newRoot);
ks.setEntry("someAlias", newEntry, null);
如果你想在某个时候保留更改的信任存储,你可以使用KeyStore#store(OutputStream,char[])来实现这一点。