use*_*353 15 java security ssl pki x509certificate
我需要忽略PKIX路径构建异常
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderExc
ption: unable to find valid certification path to requested target
Run Code Online (Sandbox Code Playgroud)
我知道如何写我自己的类实现要做到这一点X509TrustManager,我总是return true从isServerTrusted.
但是,我不想信任所有服务器和所有客户端.
我怎样才能实现这样的目标 - 即在我更换之前将部分验证传递给X509TrustFactory对象.
这就是我想要做的
public boolean isServerTrusted(X509Certificate[] chain)
{
if(chain[0].getIssuerDN().getName().equals("MyTrustedServer") && chain[0].getSubjectDN().getName().equals("MyTrustedServer"))
return true;
// else I want to do whatever verification is normally done
}
Run Code Online (Sandbox Code Playgroud)
我也不想打扰现有的isClientTrusted验证.
我怎样才能做到这一点?
Bru*_*uno 40
您可以使用以下内容来获取现有的默认信任管理器并将其包装在您自己的管理器中:
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// Using null here initialises the TMF with the default trust store.
tmf.init((KeyStore) null);
// Get hold of the default trust manager
X509TrustManager x509Tm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
x509Tm = (X509TrustManager) tm;
break;
}
}
// Wrap it in your own class.
final X509TrustManager finalTm = x509Tm;
X509TrustManager customTm = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return finalTm.getAcceptedIssuers();
}
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
finalTm.checkServerTrusted(chain, authType);
}
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
finalTm.checkClientTrusted(chain, authType);
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { customTm }, null);
// You don't have to set this as the default context,
// it depends on the library you're using.
SSLContext.setDefault(sslContext);
Run Code Online (Sandbox Code Playgroud)
然后,您可以实现自己的逻辑finalTm.checkServerTrusted(chain, authType);.
但是,您应该确保为要忽略的特定证书设置例外.
您在下面所做的是通过任何具有这些Issuer DN和Subject DN(不难伪造)的证书:
if(chain[0].getIssuerDN().getName().equals("MyTrustedServer") && chain[0].getSubjectDN().getName().equals("MyTrustedServer"))
return true;
Run Code Online (Sandbox Code Playgroud)
您可以X509Certificate从已知引用加载实例,并比较链中的实际值.
此外,checkClientTrusted并checkServerTrusted没有返回方法true或false,而是void会在默认情况下默默成功的方法.如果您期望的证书有问题,请CertificateException明确抛出.
您可以从相关的特定证书创建信任管理器,而不是实施X509TrustManager信任任何证书。从.p12或.jks密钥库或 -.crt文件加载证书(您可以将证书从浏览器复制到文件中,在 Chrome 中,通过单击挂锁并选择证书)。代码比实现你自己的要短X509TrustManager:
private static SSLSocketFactory createSSLSocketFactory(File crtFile) throws GeneralSecurityException, IOException {
SSLContext sslContext = SSLContext.getInstance("SSL");
// Create a new trust store, use getDefaultType for .jks files or "pkcs12" for .p12 files
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
// You can supply a FileInputStream to a .jks or .p12 file and the keystore password as an alternative to loading the crt file
trustStore.load(null, null);
// Read the certificate from disk
X509Certificate result;
try (InputStream input = new FileInputStream(crtFile)) {
result = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(input);
}
// Add it to the trust store
trustStore.setCertificateEntry(crtFile.getName(), result);
// Convert the trust store to trust managers
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
TrustManager[] trustManagers = tmf.getTrustManagers();
sslContext.init(null, trustManagers, null);
return sslContext.getSocketFactory();
}
Run Code Online (Sandbox Code Playgroud)
您可以通过调用来使用它HttpsURLConnection.setSSLSocketFactory(createSSLSocketFactory(crtFile))(不过,您可能希望初始化套接字工厂一次并重用它)。