我们的服务器突然无法再通过httpclient
向另一个第三服务发布请求,并且目前没有人可以登录到系统。这是我们的后端代码
public byte[] postContent(final String url, Object... data) {
Map<String, String> keyValuePairs = SystemUtils.getInstance().buildMap(new HashMap<String, String>(), data);
final long startTiming = System.currentTimeMillis();
logger.info("posting, url: " + url);
HttpClient httpClient = getHttpClient();
try {
HttpPost httpPost = new HttpPost(url);
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
for (String key : keyValuePairs.keySet()) nvps.add(new BasicNameValuePair(key, keyValuePairs.get(key)));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
ResponseHandler<byte[]> responseHandler = new ResponseHandler<byte[]>() {
public byte[] handleResponse(final HttpResponse response) throws IOException {
int status = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
logger.info("done posting, process: " + (System.currentTimeMillis() - startTiming) + "ms, url: " + url);
return entity != null ? EntityUtils.toByteArray(entity) : null;
}
};
return httpClient.execute(httpPost, responseHandler); // cannot execute
}
catch (Exception e) {
throw new SystemException(url + ", " + keyValuePairs.toString(), e);
}
}
private HttpClient getHttpClient() {
HttpClient base = new DefaultHttpClient(cm);
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,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = base.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, ssf));
HttpClient client = new DefaultHttpClient(ccm, base.getParams());
return client;
} catch(Exception ex) {
ex.printStackTrace();
return base;
}
}
这是例外
co.abc.xyz.infra.exception.SystemException: https://api.com/verify/json, {....}
at co.abc.xyz.infra.helper.HttpHelper.postContent(HttpHelper.java:155)
at co.abc.xyz.infra.helper.NexmoHelper.sendChallenge(NexmoHelper.java:70)
at co.abc.xyz.infra.controller.SecurityController.mrequestPost(SecurityController.java:89)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at
....
Caused by: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:421)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:126)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:437)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:151)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:125)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:643)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1138)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1076)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1050)
at co.abc.xyz.infra.helper.HttpHelper.postContent(HttpHelper.java:152)
... 75 more
在我的本地计算机上,一切正常,这仅在生产服务器上发生。有没有人对此有任何线索?
答案 0 :(得分:0)
您没有任何证书和信任库? 也许是因为缺少信任库... 我建议您检查每个系统环境中的根证书和证书链是否相同(和有效)。
如果您使用的是Spring / Apache HTTP Client,还可以像这样初始化SSLContext(取决于Keystore / Trustore类型):
final KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(keyStoreFile.getInputStream(), keyStorePassword.toCharArray());
final KeyStore trustStore = KeyStore.getInstance("JCEKS");
trustStore.load(trustStoreFile.getInputStream(), trustStorePassword.toCharArray());
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(
trustStore,
new TrustStrategy(){
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
})
.loadKeyMaterial(
keyStore,
keyStorePassword.toCharArray())
.build();
此外,您可以添加-Djavax.net.debug=ssl
以在JVM上打开SSL调试。
答案 1 :(得分:0)
我将电子邮件发送给第三服务询问该问题,并得到他们刚刚更新为TLSv1.2的答复,因此,默认情况下,Java 1.7使用TLSv1.1并给出了此异常。
我只需要更改行
SSLContext ctx = SSLContext.getInstance("TLS");
到
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
服务器又恢复正常。这真是悲剧。