I have the java code like this :
URL url = new URL(endPoint);
String encoding = Base64.encodeBase64String(this.key.getBytes());
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
which is opening a ssl connection. Lets say the endPoint does uses a self-singed certificate and act as a original website. Is it possible to prevent these sort of things in the java code?
Thanks in advance.
By default, the SSL implementation in Java checks against a list of trusted certification authorities, which is included in the Java VM. Unless you extend the default trust store, specify a different trust store at run time or provide your own implementation of a TrustManager and/or HostnameVerifier, you will not be able to make an SSL connection to a server with a self-signed certificate.
If you for some reason need access to the server certificates after you have established the connection, you can get these from an HttpsURLConnection like this:
URL url = new URL("https://www.google.com");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.connect();
for(Certificate crt : conn.getServerCertificates()) {
System.out.println(crt);
}
Related
I have a question regarding using an HttpUrlConnection with a https web service.
Basically, we had previously written a bunch of web services to be used in an Android application that were all http calls. We want to change those over to use https instead. Basically, what I'm concerned with, is will my existing code work properly? I had previously created a connection like the following:
HttpURLConnection myConnection = (HttpURLConnection) myURL.openConnection();
myConnection.setConnectTimeout(TIMEOUT_MILLISEC);
myConnection.connect();
This appears to be working fine with the new https web services, but I'm wondering why I don't need to change it to something like this:
HttpsURLConnection myConnection = (HttpsURLConnection) myURL.openConnection();
myConnection.setConnectTimeout(TIMEOUT_MILLISEC);
myConnection.setSSLSocketFactory(createSSLSocketFactory());
myConnection.connect();
I'm still planning on moving to a HttpsURLConnection instead, but I'm curious how older versions of our app will be affected by our intended changes.
Thanks for the help!
In docs for HttpUrlConnection you will find:
Calling openConnection() on a URL with the "https" scheme will return
an HttpsURLConnection
But since HttpsUrlConnection extends from HttpUrlConnection, this code:
HttpURLConnection myConnection = (HttpURLConnection) myURL.openConnection();
will NOT result in class cast exception if url is for https connection. You still can cast to HttpsUrlConnection - just for safety you can check with instanceof if url scheme should change.
This question already has answers here:
Trusting all certificates using HttpClient over HTTPS
(22 answers)
Closed 8 years ago.
I'm trying to hit an https site through an Android client:
URL url = new URL(myurl);
Log.d("Connection", myurl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.addRequestProperty("Content-Type", "application/json");
conn.setRequestMethod("POST");
conn.setDoInput(true);
// Starts the query
Log.d("Connection", "Connecting...");
conn.connect();
The connect call is throwing an exception:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
EDIT: I'm told the site is using a self-signed certificate, and since this is only a prototype I just need to trust all hosts so it will work. Can someone point me toward a simple example of doing this? The code I've seen online gets quite complicated, I just want to do a hacky bypass of any verification.
Are you sure that the password you are supplying is correct? This answer suggests that the connection can appear to hang if the password is incorrect.
I fixed it by creating a new .csr with the right Organizational Unit Name and Common Name
Hope you are using HTTPS in your URL.
I have got a server with self-signed certificate. I've imported it with a keytool on my computer and use
-Djavax.net.ssl.trustStore=blabla
compile argument. When I try to run the following code:
SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket("MY_URL_DIGITS", 443);
OutputStream os = socket.getOutputStream();
os.write("Test request \n".getBytes());
os.flush();
os.close();
Everything goes alright and I can see the "Test request" on the server. However, when I run:
URL url = new URL("https://MY_URL_DIGITS");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
OutputStream os = con.getOutputStream();
os.write("Test request \n".getBytes());
os.flush();
os.close();
I've got the
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present
So what is the principal difference between these two snippets?
SSLSocket by default only checks whether you trust the certificate. HttpsURLConnection checks whether you trust the certificate and also checks whether the certificate says it is coming from the same place you actually navigated to. For your HttpsURLConnection to succeed, the certificate would have to specify a subject alternative name (SAN) that was the same as the server you are conecting to. In this case the SAN would need to be "dns:MY_URL_DIGITS", where the "dns" part says you are specifying a host name rather than an IP address.
If you need additional information on how to create a certificate with a subject alternative name, see:
how to add subject alernative name to ssl certs?
The difference is that HTTPS adds a step, which can be seen in the HostnameVerifier interface. It is trying to match the hostname being connected to with the hostname in the SubjectDN or alternative names.
The following code is the common way of establishing a connection to create an array of certificates by given a URL link (that I use it in my program):
URL destinationURL = new URL("https://www.google.com");
HttpsURLConnection con = (HttpsURLConnection) destinationURL.openConnection();
con.connect();
Certificate[] certs = con.getServerCertificates();
My question is how con.getServerCertificates() really imports all the certificates chanining into Java from given a URL link, does con.getServerCertificates() always set a SSL connection to the webpage and import all the certificates chaining into an array OR does it just use (cacerts file) that comes with JKD ?
It connects to the server and gets the certificates.
There's no way it could have all the certificates already stored in a file, because then Java would have to update every time a certificate was added, removed or replaced anywhere on the Internet. And that obviously doesn't happen.
I am writing a code that connects to websites and checks some code, like a crawler. But I need to connect trough a proxy and change the IP address (so it doesn't show the client's IP in the server logs).
How can this be done through java?
You can use the java system properties to set up a proxy or pass it as command line options.
You can find some details and samples here.
Ex: Before opening the connection
System.setProperty("http.proxyHost", "myProxyServer.com");
System.setProperty("http.proxyPort", "80");
Or you can use the default network proxies configured in the sytem
System.setProperty("java.net.useSystemProxies", "true");
Since Java 1.5 you can create a instance of proxy and pass it to the openConnection() method.
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("123.0.0.1", 8080));
URL url = new URL("http://www.yahoo.com");
HttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy);
uc.connect();
Or as lisak suggested, you can use some 3rd party libraries which supports your need better.
Or you can also use HttpClient which would suit your needs better. Check out the documentation, it's brief and very informative.
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpHost proxy = new HttpHost("someproxy", 8080);
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("123.0.0.1", 8080));
URL url = new URL("http://www.yahoo.com");
HttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy);
uc.connect();
This worked for me. I was able to use the proxy for the specific connection or transfer. Earlier we were using System.setProperty which used to set it at system level and all the requests internal/external started using the same proxy.
Also Proxy.Type.HTTP works for both http and https