绕开HttpClient里的SSLPeerUnverifiedException: peer not authenticated异常
最近客户抱怨我们的cobrowsing服务无法访问他们的服务器,查看日志发现以下异常:
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:399)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:143)
最初根据搜索结果得知是我们用的HttpClient客户端不认可服务器的SSL证书导致,于是用了网上的办法来绕过服务器证书检查:
DefaultHttpClient httpclient = new DefaultHttpClient();
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("SSL");
// set up a TrustManager that trusts everything
try {
sslContext.init(null,
new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
X509Certificate[] certs, String authType) {
}
} }, new SecureRandom());定位到
} catch (KeyManagementException e) {
}
SSLSocketFactory ssf = new SSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = this.httpclient.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, ssf));
} catch (Exception e) {
log.error(e.getMessage(),e);
}
但是依然报错,后来研究得知,这个问题不是在服务器端证书的检查,而在客户端证书检查,然后我试着给了一个证书,但是依然报错。没办法只好根据调用站定位到org.apache.http.conn.ssl.SSLSocketFactory.createSocket里,派生该类,重新实现createSocket,然后不执行verify方法,经过测试就没有出现这个问题了:
SSLSocketFactory ssf = new SSLSocketFactory(ctx)
{
// non-javadoc, see interface LayeredSocketFactory
public Socket createSocket(
final Socket socket,
final String host,
final int port,
final boolean autoClose
) throws IOException, UnknownHostException {
SSLSocket sslSocket = (SSLSocket) socketfactory.createSocket(
socket,
host,
port,
autoClose
);
sslSocket.setEnabledProtocols(new String[]{"SSLv3"});
return sslSocket;
}
};
这个因为绕过了双向的证书检查,会带来潜在的不安全性比如中间人攻击,但是考虑到cobrowsing本身对安全性要求并不太高,也就算了。
Last modified on 2014-03-12