您的位置:首页 > 理论基础 > 计算机网络

HttpClient javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

2017-02-16 16:33 666 查看
最近在调用一些https的接口,然后采用的认证方式是用户名+密码。

这个时候调用接口则会提示httpclient未认证的错误,导致接口无法调用:

HttpClient javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated。

出现此问题主要是在请求过程中证书的问题,程序使用的客户端并未安装服务器要求的证书,所以会产生此问题。

下面是我找到的解决方法。

方法一: httpClient jar包版本为4.1.x

public static HttpClient getHttpClient(HttpClient base) {
try {
SSLContext ctx = SSLContext.getInstance("SSL");
X509TrustManager tm = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
};

ctx.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager mgr = base.getConnectionManager();
SchemeRegistry registry = mgr.getSchemeRegistry();
registry.register(new Scheme("https", 443, ssf));
return new DefaultHttpClient(mgr, base.getParams());
} catch (Exception e) {
logger.warn("{}", e);
return null;
}
}


调用的方法如下:

HttpClient httpClient = ToolUtil.getHttpClient(new DefaultHttpClient());


此时问题已经完美解决了。

然而在之后的使用过程中,我发现4.1版本的httpClient jar包里面没有httpPatch,但最新的4.5版本是有的。于是果断用最新的4.5.3版本的httpClient包。

用了这个jar包之后满屏幕的删除线,很多代码都被@Deprecated注解掉了。改!

解决HttpClient javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated这个问题的代码当然也是要随着一起改的了,于是乎我找到了方法二。

方法二: httpClient jar包为4.5.x版本。

public static CloseableHttpClient getHttpClient() {
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

}

@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

}

@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}}, new SecureRandom());
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().setSSLSocketFactory(socketFactory).build();
return closeableHttpClient;
} catch (Exception e) {
logger.warn("create closeable http client failed!");
return HttpClientBuilder.create().build();
}
}
调用示例:

httpClient = ToolUtil.getHttpClient();


在这个里面我遇到的最大问题是SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER 竟然也被@Deprecated注释了。然后终于找到了一个替代方案:用NoopHostnameVerifier.INSTANCE替换之。这个是在http://stackoverflow.com/questions/23201648/httpclient-4-3-x-fixing-deprecated-code-to-use-current-httpclient-implementatio 最下面一个答案中找到的。

最后附上完整的java代码,主要是给出import头文件。

import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ToolUtil {
private static final Logger logger = LoggerFactory.getLogger(ToolUtil.class);

public static HttpClient getHttpClient(HttpClient base) {
try {
SSLContext ctx = SSLContext.getInstance("SSL");
X509TrustManager tm = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
};

ctx.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager mgr = base.getConnectionManager();
SchemeRegistry registry = mgr.getSchemeRegistry();
registry.register(new Scheme("https", 443, ssf));
return new DefaultHttpClient(mgr, base.getParams());
} catch (Exception e) {
logger.warn("{}", e);
return null;
}
}

public static CloseableHttpClient getHttpClient() {
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

}

@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

}

@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}}, new SecureRandom());
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().setSSLSocketFactory(socketFactory).build();
return closeableHttpClient;
} catch (Exception e) {
logger.warn("create closeable http client failed!");
return HttpClientBuilder.create().build();
}
}

}


本文参考:

http://stackoverflow.com/questions/24752485/httpclient-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-when

http://stackoverflow.com/questions/23201648/httpclient-4-3-x-fixing-deprecated-code-to-use-current-httpclient-implementatio
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐