Home
> Java, Uncategorized > Avoiding the “javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated” with HttpClient
Avoiding the “javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated” with HttpClient
This post has moved here: http://javaskeleton.blogspot.com/2010/07/avoiding-peer-not-authenticated-with.html
Categories: Java, Uncategorized
HttpClient, https, java, ssl
Works like a charm!
Thanks!
I encountered “Cannot instantiate the type SSLSocketFactory” in the row:
SSLSocketFactory ssf = new SSLSocketFactory(ctx);
Thanks for your help~!!
Hi Sharon,
You are probably trying to instantiate a wrong SSLSocketFactory. The one you need is org.apache.http.conn.ssl.SSLSocketFactory and you probably imported the abstract javax.net.ssl.SSLSocketFactory. Sorry about this, I should have made this more clear in my post.
Here’s an overview of the import statements as they should appear at the top of your class:
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
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.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
Thanks!
I don’t use Apache HttpClient, but was able to adapt the code because your explanations were very clear.
Nicely explained, and even works great for me.
Thanks!
Very useful article.
Thank you very much Mathias.
Hi, Thanks for a very vice article.
I also had a similar issue when i was trying to use https proxy params.Though
when i use this piece of code
ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(
httpClient.getConnectionManager().getSchemeRegistry(),
ProxySelector.getDefault());
((DefaultHttpClient)httpClient).setRoutePlanner(routePlanner);
intead of this piece
HttpHost proxy = new HttpHost(httpsProxyHost,
Integer.valueOf(httpsProxyPort), “https”);
httpClient.getParams().setParameter(DEFAULT_PROXY, proxy);
I automatically got routed through proper connection.I wonder if u could help me with it.
Hi Ranjan,
If you use the ProxySelectorRoutePlanner you will use the default JRE ProxySelector, which looks at the proxy configuration of the operating system. I don’t understand what you need help with, since you say your connection works?
Not sure why it does not work for me. It still gives me the following exception.
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at com.ibm.jsse2.ec.getPeerCertificates(ec.java:114)
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:731)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:709)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:700)
Hi Gautam,
Are you sure you put in the following line: ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);? It also looks like you’re using the IBM JSSE. I didn’t test the code with the IBM JSSE.
This worked perfectly, thanks!
Thank u very much mathiasdegroof!
Your explain is very clear and useful.
Hi.
I did step by step but I get the exception. I am actually using the Apache HTTP 4.0.1 version.
Error Below:
EXCEPTION WHILE SENDING THE HANDSHAKE : = peer not authenticated
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:391)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:489)
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:562)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:700)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:625)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:603)
at com.paypal.struts.transaction.PayPalMassPayAPIListener.execute(PayPalMassPayAPIListener.java:84)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:421)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:226)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1164)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:415)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.paypal.servlets.filters.SecurityFilter.doFilter(SecurityFilter.java:85)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:118)
at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Unknown Source)
I just call the wrapper and do as the IPN listener has to do:
HttpClient httpClient = new DefaultHttpClient();
httpClient = wrapClient(httpClient);
I think you missed one step. Are you sure you put this line in your code:
ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
You say you use this in the IPN listener. The IPN listener does a call to the PayPal server, so you shouldn’t need to bypass the certificate validation: PayPal will always have a valid SSL certificate. What URL are you calling?
Ok…I am actually testing my IPN Listener againts the PayPal IPN server, (ipn.sanbox.paypal.com:443)…so I am still testing.
I thought I will be able to bypass the certificate validation by the PayPal IPN sandbox. From what you say, it is unlikely.
I did this, http://forums.oscommerce.com/topic/166092-paypal-ipn-dummies-guide/, and I got a:
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Then I tried what you said and I then got:
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated.
Any ideas?
That link you gave is pretty old: it contains posts from 2005. I think the problem is you’re using a wrong (old) PayPal url. The URL for the sandbox PayPal IPN is at https://www.sandbox.paypal.com/cgi-bin/webscr. https://ipn.sanbox.paypal.com:443 doesn’t exist (anymore?), so that’s why you got the first error.
Please see this article for an example on how to implement an IPN listener (it’s a servlet, but you can easily adapt it to struts): https://theskeleton.wordpress.com/2010/07/23/paypal-instant-payment-notification-ipn-servlet-with-httpclient-4/
mathiasde, if you test using the IPN simulator,https://developer.paypal.com/cgi-bin/devscr?cmd=_ipn-link-session and then check your network traffic, you will see that the server, ipn.sanbox.paypal.com is trying to connect send through a notification to your listener, not http://www.sanbox.paypal.com. The latter IP address is 216.113.191.33 and while the former is 216.113.191.82. The latter is correct.
I do get my payment correctly from ipn.sanbox.paypal.com and I then get the above error thrown at the line:
String rc = getRC(client.execute(post)).trim(); as in your IPN link…
It’s possible that the request to your server is originating from ipn.sandbox.paypal.com. That doesn’t mean that you should use that URL to validate the call. There is no http or https server running on ipn.sandbox.paypal.com (just go to https://ipn.sandbox.paypal.com/ with your web browser), so there is no way your request will succeed. If on the other hand you go to https://www.sandbox.paypal.com, you will see there is a https server running on that address. You don’t have to believe me, but you will never get it to work if you use the ipn.sanbox.paypal.com address. The only correct sandbox URL is https://www.sandbox.paypal.com/cgi-bin/webscr
Hi,
Thanks for your tip. However, I have another question. How do I handle client certificate authentication? I created a CSR and have it signed and returned by the server CA certificate. How do I include this signed CSR in the client side https connection? The whole process worked with Chrome and Firefox. I want to do the same using Httpclient 4.x.
Thanks.
Hi,
I’ve never had to do this myself, but the steps would probably be like this:
1. Import the key into a local keystore (don’t forget to import the trusted CA certificates as well so you have the whole certificate chain in there).
2. Create a KeyStore object and point this to your local keystore file.
3. Create a KeyManagerFactory and init this with your KeyStore object and the password to your KeyStore
4. Call the getKeyManagers() method on the KeyManagerFactory and use those in the init() method of the SSLContext (where it says “null” in the above example)
Hope this works for your.
Thanks for the prompt reply. With my limited knowledge on this subject, I don’t quite understand the purposes of step 1 and 3. For step 1, I don’t think the browser (e.g. Chrome) has my trusted CA cert becoz the trusted cert for signing CSR that I loaded in the server is not certified by “Verisign”. For step 3, what is the purpose of KeyManager?
What I did was, I created a self-signed cert (SSC) using keytool. In my code, I loaded the SSC from keystore and get its private and public keys. Using these keys I created a CSR and pass it to the server for signing. When I receive the new certificate from the server I saved it into the keystore. Using the SSLContext with the keystore, I made the SSL connection. As expected, the connection threw the “javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated”.
I searched the web and trying to look for the process of how a browser handle client side SSL connection. I wonder if you can advice me where to look for more info.
I suppose you’re right. Like I said, I’ve never done this before myself.
Your code should probably look something like this:
public 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;
}
};
KeyStore ks = KeyStore.getInstance(“jks”);
String keystorePassord = “pass”;
ks.load(new FileInputStream(“c:/keystore_file”), keystorePassord.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, keystorePassord.toCharArray());
ctx.init(kmf.getKeyManagers(), 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;
}
}
}
If you still get errors with that code, please look at the javadoc at the top of the following class: http://svn.apache.org/viewvc/httpcomponents/oac.hc3x/trunk/src/contrib/org/apache/commons/httpclient/contrib/ssl/AuthSSLProtocolSocketFactory.java?view=markup which will tell you how to import the correct keys into your keystore.
Hope this works for you.
Your tip was very helpful. I finally got it figured. The key to the solution lied in KeyManager and TrustManager. KeyManager to choose the right certificate to use in the SSL connection and empty TrustManager extension to enable the client to connect to the server. Workable (not tested to work in all context) codes follow,
import java.io.IOException;
import java.net.Socket;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509TrustManager;
import javax.security.auth.x500.X500Principal;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.jce.PKCS10CertificationRequest;
import org.bouncycastle.util.encoders.Base64;
public class TestClientSSLConnection
{
public static void main() throws Exception
{
HttpClient client = new DefaultHttpClient();
HttpPost createCertPost = new HttpPost(“http://localhost:8080/createUser”);
final KeyPair keyPair = KeyPairGenerator.getInstance(“RSA”).generateKeyPair();
List formParams = new ArrayList();
formParams.add(new BasicNameValuePair(“userName”, generateRandomString()));
String generatedGivenName = generateRandomString();
formParams.add(new BasicNameValuePair(“givenName”, generatedGivenName));
String generatedFamilyName = generateRandomString();
formParams.add(new BasicNameValuePair(“familyName”, generatedFamilyName));
formParams.add(new BasicNameValuePair(“email”, generateRandomEmail()));
String generatedOrganization = generateRandomString();
formParams.add(new BasicNameValuePair(“org”, generatedOrganization));
//formParams.add(new BasicNameValuePair(“keygen”, new String(Base64.encode(createCertRequest(privateKeyEntry.getPrivateKey(), masterCert.getPublicKey()).getEncoded()))));
formParams.add(new BasicNameValuePair(“keygen”, new String(Base64.encode(createCertRequest(keyPair.getPrivate(), keyPair.getPublic()).getEncoded()))));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, “UTF-8”);
createCertPost.setEntity(entity);
createCertPost.setHeader(“User-Agent”,
“Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.558.0 Safari/534.10”);
HttpResponse res = null;
try
{
res = client.execute(createCertPost);
}
catch (IOException e)
{
fail(“Failed to connect to server.”); // fail(…) is a method in JUnit’s Testcase. Use log instead if not using Testcase. Same for others.
}
if (res.getStatusLine().getStatusCode() != 200)
{
fail(“Failed to submit new user information.”);
}
String responseBody = EntityUtils.toString(res.getEntity());
HttpGet retrieveCertGet = new HttpGet(“http://localhost:8080/retrieveMyCertificate?&certId=” + certId);
try
{
res = client.execute(retrieveCertGet);
if (res.getStatusLine().getStatusCode() != 200)
{
fail(“Failed to retrieve signed certificate.”);
}
}
catch (Exception e)
{
fail(“Failed to retrieve user certificate.”);
LOG.fatal(e);
}
final X509Certificate certificateResponse = (X509Certificate)CertificateFactory.getInstance(“X.509”)
.generateCertificate(res.getEntity().getContent());
try
{
certificateResponse.checkValidity();
}
catch(Exception e)
{
fail(“Signed certificate failed validity check.”);
}
X509TrustManager tm = new X509TrustManager()
{
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException
{
}
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException
{
// leaving empty to denote accepting all server certificates
}
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
};
SSLContext ctx = null;
try
{
ctx = SSLContext.getInstance(“TLS”);
}
catch (Exception e)
{
fail(“Failed to create SSL socket factory.”);
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
X509ExtendedKeyManager keyManager = new X509ExtendedKeyManager()
{
@Override
public String[] getClientAliases(String s, Principal[] principals)
{
return new String[0];
}
@Override
public String chooseClientAlias(String[] strings, Principal[] principals, Socket socket)
{
return “”;
}
@Override
public String[] getServerAliases(String s, Principal[] principals)
{
return new String[0];
}
@Override
public String chooseServerAlias(String s, Principal[] principals, Socket socket)
{
return null;
}
@Override
public X509Certificate[] getCertificateChain(String s)
{
// use the signed CSR to connect to the server
return new X509Certificate[] {certificateResponse};
}
@Override
public PrivateKey getPrivateKey(String s)
{
return keyPair.getPrivate();
}
};
ctx.init(new KeyManager[] {keyManager}, new TrustManager[] {tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx);
ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpGet secureLogon = new HttpGet(“https://localhost:8443/success.html”);
client.getConnectionManager().getSchemeRegistry().register(new Scheme(“https”, ssf, 8443));
res = client.execute(secureLogon);
if (res.getStatusLine().getStatusCode() != 200)
{
fail(“Failed to connect to secure site”);
}
}
private PKCS10CertificationRequest createCertRequest(PrivateKey privateKey, PublicKey publicKey) throws NoSuchAlgorithmException, SignatureException, InvalidKeyException, NoSuchProviderException
{
return new PKCS10CertificationRequest(“SHA512withRSA”,
new X500Principal(“O=as UID=cert1 CN=Test V3 Certificate”),
publicKey,
new DERSet(),
privateKey);
}
private String generateRandomEmail()
{
return “testcase_” + RandomStringUtils.randomAlphabetic(10) + “@localtest.com”;
}
private String generateRandomString()
{
return “testcase_” + RandomStringUtils.randomAlphabetic(10);
}
}
I’m glad you got it to work. Thank you for posting your code, I’m sure it will help someone out in the future!
I’m from China.Thanks a lot!
TH Lim,
setHostnameVerifier is deprecated, can you tell me how will your code change accordingly? I am kind of confused.
Richard
Actually I got around my earlier question by doing this:
SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER );
instead of ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Now I have another problem with httpclient’s authscope method. I was thinking it will establish a permanent session with the host that I am specifying but it doesn’t seem to. I am not sure how to establish a session to talk to the REST service I am talking to within the same class.
I get the following error:
executing request GET https://dam-vchg01.land.virtual/vCenter-CB/api/costModels/ HTTP/1.1
—————————————-
HTTP/1.1 200 OK
Response content length: 318
Here is my code:
public class ClientAuthentication {
public static void main(String[] args) throws Exception {
DefaultHttpClient httpclient = HttpClientIgnoreInvalidSSLCertificate.createClient();
//DefaultHttpClient httpclient = new DefaultHttpClient();
try {
httpclient.getCredentialsProvider().setCredentials(
new AuthScope(“dam-vchg01.land.virtual”, 443),
new UsernamePasswordCredentials(“rjose”, “rjose6345”));
HttpGet httpget = new HttpGet(“https://dalm-vchg01.land.virtual/vCenter-CB/api/costModels/”);
System.out.println(“executing request” + httpget.getRequestLine());
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
System.out.println(“—————————————-“);
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println(“Response content length: ” + entity.getContentLength());
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));
String line = “”;
while ((line=reader.readLine())!= null)
{
System.out.println(line);
}
} catch (IOException ex) {
ex.printStackTrace();
throw ex;
} catch (RuntimeException ex) {
httpget.abort();
throw ex;
} finally {
}
}
EntityUtils.consume(entity);
} finally {
httpclient.getConnectionManager().shutdown();
}
}
}
Please tell me how to get around this. Is there something that i am missing.
Thanks,
Richard
Ok I see 3 questions here:
1. They must have deprecated the setHostnameVerifier() in a recent version, because it wasn’t deprecated in the version I used when I wrote the article (v4.0.1, which was the latest version at that time). It’s good that you found a workaround.
2. I don’t know what you mean by a “permanent session”. There is no such thing in HTTP. Sessions are implemented on the server, either by passing a cookie or a session id parameter in each request. Maybe you mean TCP connection reuse? This is something that HTTPClient will try to do by default (see http://hc.apache.org/httpcomponents-client-ga/tutorial/html/httpagent.html for more info on how to modify this behavior).
3. You also say you get an error, but I don’t see any errors posted, only a HTTP/1.1 200 OK, which means everything went well…
I’m still getting the Peer not authenticated exception, following the code above. Below is the exception and snippet of code I’m using. Any ideas? Thanks much for your help
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.connectSocket(SSLSocketFactory.java:339)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:123)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
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)
public void sendMessage(String url) throws Exception {
X509TrustManager tm = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted( java.security.cert.X509Certificate[] chain,
String authType)
throws
java.security.cert.CertificateException {
// TODO Auto-generated method stub
}
public void checkServerTrusted ( java.security.cert.X509Certificate[] chain,
String authType)
throws java.security.cert.CertificateException {
// TODO Auto-generated method stub
}
};
long token = System.currentTimeMillis();
log.info(TAG + “sendMessage() ” + token + ” url -> ” + url);
//System.setProperty(“sun.security.ssl.allowUnsafeRenegotiation”, “true”);
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, KEYSTORE_PASS.toCharArray());
DefaultHttpClient dhc = new DefaultHttpClient();
SSLContext sc = SSLContext.getInstance(“TLS”);
sc.init(kmf.getKeyManagers(), new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(sc);
ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//SSLSocketFactory ssf = new SSLSocketFactory(keyStore, KEYSTORE_PASS, null);
Scheme s = new Scheme(“https”, ssf, 443);
ClientConnectionManager ccm = dhc.getConnectionManager();
ccm.getSchemeRegistry().register(s);
HttpGet hp = new HttpGet(url);
HttpResponse hr = dhc.execute(hp);
log.info(TAG + “sendMessage() ” + token + ” response -> ” + hr.getStatusLine());
log.info(TAG + “sendMessage() ” + token + ” response -> ” + hr.getEntity().getContent().toString());
ccm.shutdown();
}
Hi Beena,
I tried your code, except for the KeyManagerFactory, and it works for me. So I assume the server is rejecting your clients certificate. This means it’s the client authentication that’s failing and not the server authentication. You’ll need to make sure that your keystore contains a certificate that is accepted by the server you are connecting to.
Hope this helps.
Folks, it works!!! Just saved myself a ton of time and effort. Thank you!
Hello,
Your code was very helpful. My legal department is asking whether you could license this code snippet to us or make some statement about it being public domain. If you attach an Apache 2.0 or BSD style license, that would be easiest.
Thank you!
— Victor
Hi Victor,
I wouldn’t worry too much about it: these licenses are generally used for libraries and this is just a code snippet. Anyone is free to use it in any way they want. I’ll add a comment to the class just to make sure.
Hi, and thanks! Even code snippets cannot be used by in a commercial application (at least at our company) unless it’s clearly labeled with a license or public domain statement. Thanks so much for your help!
— Victor
For those who are still getting “javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated”, you may want to turn on ssl debug (-Djavax.net.debug=ssl) to see what the problem is. For my purpose, I actually don’t want to trust all certs, so I have trusted root certificates in my truststore. However, I will sometimes still get javax.net.ssl.SSLPeerUnverifiedException for a web server that I’ve been able to connect to before. Turning on ssl debug reveals that during the handshake, if my app should lose connection to the server due to Connection reset (e.g. java.net.SocketException: Connection reset), it will throw javax.net.ssl.SSLPeerUnverifiedException. So the exception is misleading. The stacktrace (snippet below) shows this is caused by the jre so unfortunately, we will have to wait for Oracle to fix this issue.
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.connectSocket(SSLSocketFactory.java:390)
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:562)
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)
SSL debug shows SocketException as real cause:
Thread-12, WRITE: TLSv1 Handshake, length = 113
Thread-12, handling exception: java.net.SocketException: Connection reset
Thread-12, SEND TLSv1 ALERT: fatal, description = unexpected_message
Thread-12, WRITE: TLSv1 Alert, length = 2
Thread-12, Exception sending alert: java.net.SocketException: Broken pipe
Thread-12, called closeSocket()
Thread-12, called close()
Thread-12, called closeInternal(true)
HI,
Can anyone please send me sample code to connect to HTTPS URL with user id/password and download some file. I was able to do this with simple URL without any credential but for login URLs, its returning me SSO page in response 😦 …please advice! I am using HttpClient 4.1 jars.
MAny THanks
Shilpa
Hi Shilpa,
This depends on the authentication mechanism used. It is basic authentication or some kind of form-based authentication?
Shilpa,
This thread is referring to client side HTTPS. From your requirement, what you want to resolve is a typical HTTPS (on server side) connection with a page basic authentication and a download link. There are bits and pieces documentations scattered. It is just tedious to combine them together.
Thanks for ur responses.
Yes, it is page basic authentication(single sign on). Sorry about posting my queries here but if you guys know any reference link, please share…it will be great help!!
THanks again.
SHilpa
Hi Shilpa,
Please read this: http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html, it probably contains what you need. Please note that SSO (single sign on) isn’t an authentication scheme: it’s just a method by which a user only logs in once for multiple services. It can be implemented in different ways…
Thanks mathiasde! I looked at the link, it has 4 types of authentication but couldn’t find anything for CSP authentication type which is used in our SSO 😦
I also tried NTLM type and did windows authentication setup in my SSO but still no luck ….I am not sure whether am I trying a valid scenario here or is it something which is not possible with HttpClient…
Wel you’ll need to figure out what authentication your CSP uses first. CSP isn’t an authentication scheme. Maybe it uses Kerberos, so you could try that…
hmm need to dig into CSP 🙂 its on customer side so lit slow to get all answers.
I tried kerberos code as well, but it too return the SSO html page in response 😦 atleast I am not getting any exception so may be there is some hope to work ahead 🙂