我正在为使用REST API的应用程序创建一些单元测试。当我尝试向服务器URL(https://some.server.com)发送HttpPost请求时,我得到了这个:
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:352)
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)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:108)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554)
服务器具有经过验证的HTTPS证书。此外,当我在生产中运行它时,它工作正常。所以我认为它与JUnit和/或我的本地计算机有关。
我也在使用用这个创建的HttpClient:
public static class WebClientDevWrapper {
public static HttpClient wrapClient(HttpClient base) {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx);
ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = base.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", ssf, 443));
return new DefaultHttpClient(ccm, base.getParams());
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
}
AFAIK,如果我使用上面的代码创建一个HTTPClient,它应该避免使用SSLPeerUnverifiedException
,但它似乎无效。
那我怎么解决这个问题呢?我已经尝试了更多方法来创建不抱怨SSL证书的HttpClients,但到目前为止还没有任何工作。
答案 0 :(得分:3)
你碰巧在使用Linux吗?我在Ubuntu系统上使用Java和SSL时遇到了疯狂的问题。它与/ etc / hosts文件映射localhost到127.0.1.1而不是127.0.0.1有关。根据IANA映射,两者都同样有效,但如果不是127.0.0.1,Java似乎也会退出。当问题出现时,它甚至很少通过握手,所以即使你完全禁用了所有的证书检查,它仍然会以意想不到的方式失败。
答案 1 :(得分:1)
对这个问题的大多数回答(在StackOverflow和其他地方)都花费了太多时间专注于Java代码本身,而且经常给出的答案是绕过所有主机的SSL验证。请将此作为绝对的最后手段,即使它只是一个开发环境,并且只在必要时根据需要而不是全面地执行。这是一种糟糕的做法,我想知道“仅限开发环境”的代码是否经常将其投入生产。
现实情况是错误完全准确,在某些情况下实际上有更好的选择。您只会在以下情况下收到此错误:
第一个要点有自己的问题。当没有安装证书但是应用程序仍在通过HTTP提供流量时,为什么要在任何生产场景中连接到主机都是值得怀疑的。如果您通过该连接发送敏感用户数据,那么您已经创建了严重的安全漏洞。这个要点的唯一解决方案是绕过验证,除非你只是“抓取”或“抓取”内容,否则根本就没有解决方案。
不幸的是,第二个要点也是如此。如果必须通过SSL连接到主机,唯一的解决方案是绕过SSL验证。即使将证书添加到信任库也不会在证书过期或使用无效的CN创建时阻止此异常。如果您与主持人有持续的关系,请询问他们是否可以解决问题。
第三个和第四个要点的解决方案取决于您与要连接的主机建立的信任级别,但比简单地绕过所有SSL主机验证要好得多。只需将证书添加为可信证书(授权)。
首先,使用您喜欢的浏览器下载证书。 Firefox和Chrome都提供了下载域证书的实用程序。 This question and answers from SuperUser provide some details。在Java JDK中,CA信任库位于[JAVA_HOME] / jre / lib / security / cacerts。使用以下keytool命令将下载的证书添加到其中:
keytool -import -trustcacerts -alias domainalias -file host.crt -keystore cacerts
有关更多信息和其他keytool命令,我想使用以下页面:
答案 2 :(得分:0)
如果我使用上面的代码创建一个HTTPClient,它应该避免 SSLPeerUnverifiedException
完全没有。所有不安全的X509TrustManager都接受任何对等证书,无论是否值得信赖,这完全没有意义。您所看到的是对等方根本没有发送证书
答案 3 :(得分:0)
这是我的背景解决方案。
我在企业环境中使用Windows 7,这意味着我有代理。 SOAP URL处于测试环境中,该公司代理无法看到它。
确保在 File->您将代理设置设置为无的首选项。
问候,卡洛。