本文介绍了阿帕奇的HttpClient能够DIRECT时的通讯通过HTTPS但不通过代理服务器错误:javax.net.ssl​​.SSLPeerUnverifiedException:同行不认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看了,虽然许多不同的例子,但我目前有尝试通过使用HTTPS代理沟通的困难。我有一个包装创建的Apache的HttpClient如下code看到。

目前如果我做我的电话没有设置代理,将使用来自SSLSocketFactory的我信任,并正确允许通过SSL通信。唯一需要的证书是不需要身份验证的威瑞信服务器证书。

当我设置一个代理我得到一个错误说:

javax.net.ssl​​.SSLPeerUnverifiedException:同行未通过身份验证

我觉得我必须失去了某种类型的代理设置的,这使得代理连接使用相同的SSLSocketFactory的?

我-Djavax.net.debug = SSL测试,并直接去时,我可以看到更多的SSL活动。当我使用我直接能看到的所有键加载并与请求发送,当我使用代理我只看到:

  httpConnector.receiver.3,setSoTimeout(30000)呼吁
%%无缓存的客户端会话
***的ClientHello,使用TLSv1
RandomCookie:GMT:1307565311字节= {184,216,5,151,154,212,232,96,69,73,240,54,236,26,8,45,109,9,192,
227,193,58,129,212,57,249,205,56}
会话ID:{}
密码套件:[SSL_RSA_WITH_RC4_128_MD5,SSL_RSA_WITH_RC4_128_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_C
BC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE_DSS_WITH
_3DES_EDE_CBC_SHA,SSL_RSA_WITH_DES_CBC_SHA,SSL_DHE_RSA_WITH_DES_CBC_SHA,SSL_DHE_DSS_WITH_DES_CBC_SHA,SSL_RSA_EXPORT_WITH
_RC4_40_MD5,SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
]
COM pression方法:{0}
***
httpConnector.receiver.3,写:使用TLSv1握手,长度= 73
httpConnector.receiver.3,写:客户端的SSLv2 Hello报文,长度= 98
httpConnector.receiver.3,处理异常:javax.net.ssl​​.SSLException:无法识别的SSL消息,明文连接?
httpConnector.receiver.3,发送的TLSv1警告:致命的,说明= unexpected_message
httpConnector.receiver.3,写:使用TLSv1警报,长度= 2
httpConnector.receiver.3,叫则closesocket()
httpConnector.receiver.3,IOException异常在的getSession():javax.net.ssl​​.SSLException:无法识别的SSL消息,美国康涅狄格州明文
挠度?
httpConnector.receiver.3,所谓的close()
httpConnector.receiver.3,叫closeInternal(真)
httpConnector.receiver.3,所谓的close()
httpConnector.receiver.3,叫closeInternal(真)
2011-12-20 11:11:59401 [httpConnector.receiver.3]信息 - JavaScript方法的addEvent扔类型的类共同的异常
m.alarmpoint.integrationagent.soap.exception.SOA prequestException与消息javax.net.ssl​​.SSLPeerUnverifiedException:PE
呃未经过身份验证,唯一的例外会将会传播调用堆栈。

谁能帮帮忙吧。这里是我的code设置了代理和SSLSocketFactory的。

  VAR的客户= httpClientWrapper.getHttpClient();
VAR代理=新HttpHost(PROXY_HOST,proxy_port使用https开头);
client.getParams()的setParameter(ConnRoutePNames.DEFAULT_PROXY,代理)。VAR AUTH preF =新的ArrayList();
AUTH pref.add(AuthPolicy.BASIC);client.getParams()的setParameter(AuthPNames.PROXY_AUTH_ preF,AUTH preF)。ServiceAPI.getLogger()调试(KeyStore.getDefaultType()+ KeyStore.getDefaultType())。
变种的trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
VAR河道=新的FileInputStream(新文件(CONF / my.truststore));
尝试{
ServiceAPI.getLogger()调试(渐trustore);
trustStore.load(插播广告的changeit.split(''));
} {最后
instream.close();
}
VAR的SocketFactory =新的SSLSocketFactory(的trustStore);
VAR SCH =新计划(https开头,的SocketFactory,443);。client.getConnectionManager()getSchemeRegistry()寄存器(SCH)。

堆栈跟踪:

 产生的原因:javax.net.ssl​​.SSLPeerUnverifiedException:同行不认证
在com.sun.net.ssl​​.internal.ssl.SSLSessionImpl.getPeerCertificates(来源不明)
在org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
在org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:390)
在org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:488)
在org.apache.http.conn.scheme.SchemeSocketFactoryAdaptor.connectSocket(SchemeSocketFactoryAdaptor.java:62)
在org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:148)
在org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149)
在org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121)
在org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:561)
在org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
在org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
在org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
在org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)


解决方案

下面是在亚伦的解决方案,一个变体,在Java中(VS Groovy中)。该解决方案还避免了HttpClientWrapper类(其中这是否是从哪里来的?),并直接加载代理证书。这是对的HttpClient 4.2编写的(但我认为它应该有4.0工作)。作为额外的奖励,它包括用于Windows代理如Microsoft Forefront TMG的代理身份验证的例子。

我花了足够长的时间来拼凑这个在一起我想我应该分享:

 的HttpParams PARAMS =新BasicHttpParams();
    DefaultHttpClient.setDefaultHttpParams(PARAMS); //默认参数添加到我们正在构建的参数设置
    DefaultHttpClient客户端=新DefaultHttpClient(PARAMS);    密钥库的trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    trustStore.load(NULL);    InputStream的certStream =新的FileInputStream(证书文件);
    CertificateFactory CF = CertificateFactory.getInstance(X.509);
    x509证书证书=(x509证书)cf.generateCertificate(certStream);
    certStream.close();
    trustStore.setCertificateEntry(代理证书,证书);    的SSLSocketFactory的SocketFactory =新的SSLSocketFactory(的trustStore);
    。client.getConnectionManager()getSchemeRegistry()寄存器(新计划(https开头,443的SocketFactory))。    client.getParams()的setParameter(ConnRoutePNames.DEFAULT_PROXY,
                           新HttpHost(我的代理,8080));    //如果您的代理是基于和放大器的Windows时,才需要这3条线路;需要验证
    AuthScope范围=新AuthScope(MYPROXY,8080,空,AuthPolicy.NTLM);
    凭证凭证=新NTCredentials(用户名,的changeit,工作站,MY-DOMAIN);
    client.getCredentialsProvider()setCredentials方法(适用范围,证书)。    HTTPGET GET =新HTTPGET(https://mysite.com/resource);
    字符串结果= client.execute(GET,新BasicResponseHandler());    的System.out.println(结果);

I have read though many different examples but I am currently having difficulties trying to communicate via a proxy using HTTPS. I have a wrapper to create a Apache HttpClient as seen in the code below.

Currently if I make my call without setting up a proxy it will use my truststore from the SSLSocketFactory and correctly allow the communication via SSL. The only certificate required is a verisign server certificate which does not require authentication.

When I setup a proxy I get an error saying:

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

I feel that I must be missing some type of proxy setup which makes the proxy connection use the same SSLSocketFactory?

I tested with -Djavax.net.debug=ssl and I can see a lot more SSL activity when going direct. When I use direct I can see all the keys loaded and sent with the request, when I use the proxy I only see:

httpConnector.receiver.3, setSoTimeout(30000) called
%% No cached client session
*** ClientHello, TLSv1
RandomCookie:  GMT: 1307565311 bytes = { 184, 216, 5, 151, 154, 212, 232, 96, 69, 73, 240, 54, 236, 26, 8, 45, 109, 9, 192,
227, 193, 58, 129, 212, 57, 249, 205, 56 }
Session ID:  {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_C
BC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH
_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH
_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
]
Compression Methods:  { 0 }
***
httpConnector.receiver.3, WRITE: TLSv1 Handshake, length = 73
httpConnector.receiver.3, WRITE: SSLv2 client hello message, length = 98
httpConnector.receiver.3, handling exception: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
httpConnector.receiver.3, SEND TLSv1 ALERT:  fatal, description = unexpected_message
httpConnector.receiver.3, WRITE: TLSv1 Alert, length = 2
httpConnector.receiver.3, called closeSocket()
httpConnector.receiver.3, IOException in getSession():  javax.net.ssl.SSLException: Unrecognized SSL message, plaintext conn
ection?
httpConnector.receiver.3, called close()
httpConnector.receiver.3, called closeInternal(true)
httpConnector.receiver.3, called close()
httpConnector.receiver.3, called closeInternal(true)
2011-12-20 11:11:59,401 [httpConnector.receiver.3] INFO - The JavaScript method AddEvent threw an exception of type class co
m.alarmpoint.integrationagent.soap.exception.SOAPRequestException with message "javax.net.ssl.SSLPeerUnverifiedException: pe
er not authenticated".  The exception will be propogated up the call stack.

Can anyone help out please. Here is my code for setting up the proxy and SSLSocketFactory.

var client = httpClientWrapper.getHttpClient();
var proxy = new HttpHost(PROXY_HOST, PROXY_PORT, "https"); 
client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 

var authpref = new ArrayList();
authpref.add(AuthPolicy.BASIC);

client.getParams().setParameter(AuthPNames.PROXY_AUTH_PREF, authpref);

ServiceAPI.getLogger().debug("KeyStore.getDefaultType() " + KeyStore.getDefaultType());


var trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());        
var instream = new FileInputStream(new File("conf/my.truststore")); 
try {
ServiceAPI.getLogger().debug("getting trustore");
trustStore.load(instream, "changeit".split(''));
} finally {
instream.close();
}


var socketFactory = new SSLSocketFactory(trustStore);
var sch = new Scheme("https", socketFactory, 443);

client.getConnectionManager().getSchemeRegistry().register(sch);

Stack trace:

Caused by: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(Unknown Source)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:390)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:488)
at org.apache.http.conn.scheme.SchemeSocketFactoryAdaptor.connectSocket(SchemeSocketFactoryAdaptor.java:62)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:148)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:561)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)
解决方案

Here's a variant on aaron's solution, in Java (vs Groovy). This solution also avoids the HttpClientWrapper class (where does that come from?), and loads the proxy's certificate directly. It is written against HttpClient 4.2 (but I think it should work with 4.0). As an added bonus it includes an example of proxy authentication for a Windows proxy such as Microsoft ForeFront TMG.

It took me long enough to piece this together that I figured I should share it:

    HttpParams params = new BasicHttpParams();
    DefaultHttpClient.setDefaultHttpParams( params );   // Add the default parameters to the parameter set we're building
    DefaultHttpClient client = new DefaultHttpClient( params );

    KeyStore trustStore = KeyStore.getInstance( KeyStore.getDefaultType() );
    trustStore.load( null );

    InputStream certStream = new FileInputStream( "cert-file" );
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    X509Certificate cert = (X509Certificate)cf.generateCertificate(certStream);
    certStream.close();
    trustStore.setCertificateEntry( "proxy-cert", cert );

    SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
    client.getConnectionManager().getSchemeRegistry().register( new Scheme( "https", 443, socketFactory ));

    client.getParams().setParameter( ConnRoutePNames.DEFAULT_PROXY, 
                           new HttpHost( "my-proxy", 8080 ));

    // These 3 lines are only needed if your proxy is Windows based & requires authentication
    AuthScope scope = new AuthScope( "myproxy", 8080, null, AuthPolicy.NTLM );
    Credentials credentials = new NTCredentials( "username", "changeit", "WORKSTATION", "MY-DOMAIN" );
    client.getCredentialsProvider().setCredentials( scope, credentials );

    HttpGet get = new HttpGet( "https://mysite.com/resource" );
    String result = client.execute( get, new BasicResponseHandler() );

    System.out.println( result );

这篇关于阿帕奇的HttpClient能够DIRECT时的通讯通过HTTPS但不通过代理服务器错误:javax.net.ssl​​.SSLPeerUnverifiedException:同行不认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-31 12:53