在我们自己的项目中由于代码重构以及升级,将jdk环境从jdk1.6换成了1.7,这时候我们发现了一个问题,访问某些https网站时候,出现了Certificates does not conform to algorithm constraints的异常,上网搜索了下,没有什么现成的解决方案,倒是找到了一些原因,具体原因可以看下面的链接
总的来说在1.7这个问题其实已经修补了,但是如果有一些类实现了X509TrustManager这个接口,而不是extends X509ExtendedTrustManager 这个抽象类,那么jdk底层会使用AbstractTrustManagerWrapper这个类来包裹实现X509TrustManager接口的类,当使用这个wrapper的时候,一定程度上有时候会绕过已经被修复的问题,导致Certificates does not conform to algorithm constraints会再度复现。所以解决方案就有了
在httpclient中我们实现sslcontext和sslcontextbuilder 在sslcontextbuilder里我们使用自己的trustmanager类去extends X509ExtendedTrustManager 具体代码如下:
private static SSLConnectionSocketFactory buildSSLConnectionFactory()
throws FileNotFoundException, KeyStoreException,
NoSuchAlgorithmException, KeyManagementException {
SSLContext sslContext = new MySSLContextBuilder().useTLS().loadTrustMaterial(null, new TrustStrategy()
{
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
})
.build();
return new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
}
static class MySSLContext extends SSLContext {
public MySSLContext(SSLContextSpi sslContextSpi, Provider provider, String s) {
super(sslContextSpi, provider, s);
}
public static SSLContextBuilder custom() {
return new MySSLContextBuilder();
}
}
static class MySSLContextBuilder extends SSLContextBuilder {
static final String TLS = "TLS";
static final String SSL = "SSL";
private String protocol;
private Set<KeyManager> keymanagers;
private Set<TrustManager> trustmanagers;
private SecureRandom secureRandom;
public MySSLContextBuilder() {
super();
this.keymanagers = new HashSet<KeyManager>();
this.trustmanagers = new HashSet<TrustManager>();
}
static class TrustManagerDelegate extends X509ExtendedTrustManager {
private final X509TrustManager trustManager;
private final TrustStrategy trustStrategy;
TrustManagerDelegate(final X509TrustManager trustManager, final TrustStrategy trustStrategy) {
super();
this.trustManager = trustManager;
this.trustStrategy = trustStrategy;
}
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket) throws CertificateException {
}
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) throws CertificateException {
}
public void checkClientTrusted(
final X509Certificate[] chain, final String authType) throws CertificateException {
this.trustManager.checkClientTrusted(chain, authType);
}
public void checkServerTrusted(
final X509Certificate[] chain, final String authType) throws CertificateException {
if (!this.trustStrategy.isTrusted(chain, authType)) {
this.trustManager.checkServerTrusted(chain, authType);
}
}
public X509Certificate[] getAcceptedIssuers() {
return this.trustManager.getAcceptedIssuers();
}
}
public SSLContextBuilder loadTrustMaterial(
final KeyStore truststore,
final TrustStrategy trustStrategy) throws NoSuchAlgorithmException, KeyStoreException {
final TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmfactory.init(truststore);
final TrustManager[] tms = tmfactory.getTrustManagers();
if (tms != null) {
if (trustStrategy != null) {
for (int i = 0; i < tms.length; i++) {
final TrustManager tm = tms[i];
if (tm instanceof X509TrustManager) {
tms[i] = new MySSLContextBuilder.TrustManagerDelegate(
(X509TrustManager) tm, trustStrategy);
}
}
}
for (final TrustManager tm : tms) {
this.trustmanagers.add(tm);
}
}
return this;
}
}
···