Android SSL HTTP Request using self signed cert and CA
Solved by using: HttpsURLConnection
URLConnection conn = null;
URL url = new URL(strURL);
conn = url.openConnection();
HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
This seems to work fine with user installed CA certificates.
Android - Obtain self-signed server certificate and add to trusted keystore
The simple solution
Here's a code example of a trust manager callback. From the callback you can either store the self-signed certificates or just accept them right away. But you SHOULD NOT do neither. By accepting self-signed certs, you are subject to connecting to fake or malicious servers which can steal personal data, install malware, and do other nasty things.
The better-than-simple solution
If a server offers a self-signed certificate that you, the developer, trust at compile time, you can bundle the cert into the app like you're already doing. It would be much better if the server had a CA-signed certificate, but if you really need to connect to a server that offers a self-signed cert, this will (have to) do.
A nicer solution
Never accept self-signed certificates in runtime. If you want to allow your users to connect to these kind of servers, you can show a warning message like "proceed at your own risk" before accepting the self-signed cert.
accepting HTTPS connections with self-signed certificates
The first thing you need to do is to set the level of verification.
Such levels is not so much:
- ALLOW_ALL_HOSTNAME_VERIFIER
- BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
- STRICT_HOSTNAME_VERIFIER
Although the method setHostnameVerifier() is obsolete for new library apache, but for version in Android SDK is normal.
And so we take ALLOW_ALL_HOSTNAME_VERIFIER
and set it in the method factory SSLSocketFactory.setHostnameVerifier()
.
Next, You need set our factory for the protocol to https. To do this, simply call the SchemeRegistry.register()
method.
Then you need to create a DefaultHttpClient
with SingleClientConnManager
.
Also in the code below you can see that on default will also use our flag (ALLOW_ALL_HOSTNAME_VERIFIER
) by the method HttpsURLConnection.setDefaultHostnameVerifier()
Below code works for me:
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
DefaultHttpClient client = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
// Set verifier
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
// Example send http request
final String url = "https://encrypted.google.com/";
HttpPost httpPost = new HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);
Trust my own self-signed certificate in local network using Android Native, Android Studio and retrofit
Shlomi Katriel's answer was something I had already tried, but it led me to the solution indirectly. Please keep in mind that the only reason I was able to solve this was because I have root access to the server and can do with it as I please.
This
answer was basically the key to solving the whole thing. I will post all the steps in case someone else needs this.
Step 1
Create your self-signed certificate. In my case, I used the openssl utility. It is very important to include the -addext flag. Here is an example taken directly from the answer I linked above:
openssl req \
-newkey rsa:2048 \
-nodes \
-x509 \
-days 36500 -nodes \
-addext "subjectAltName = IP.1:1.2.3.4" \
-keyout /etc/ssl/private/nginx-selfsigned2.key \
-out /etc/ssl/certs/nginx-selfsigned2.crt
Replace 1.2.3.4 with the local ip of your server. This will include the server's local ip in the subjectAltName property of the certificate. Without this, you will keep getting the error "Hostname ... not verified ..."
Using the certificate in a running nginx instance is a different subject which can be done easily and there are plenty of resources online.
Step 2 Open android studio and create a new android resource directory (if you don't already have it) under res
named raw
. Inside this directory, copy the contents of the .crt file that the command above produced.
Step 3 Create an android resource directory under res
named xml
. In there, create a new xml file which in my case I called network_security_config.xml
. In there, I inserted the following:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="@raw/certificate"/>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>
Instead of "certificate", use the filename of the certificate file you copied in step 2.
Step 4 Add android:networkSecurityConfig="@xml/network_security_config"
to the application element in your AndroidManifest.xml
android - https with server having self-signed certificate
Do I have separately get my server's self-signed certificate ?
I don't know what "separately" means in this context, but you need the keystore containing the self-signed certificate for the purposes of validation.
Will the API not get that for me automatically in some way ?
How could it? The point behind validating a certificate is to confirm that it is indeed correct, and that your user is not the victim of a man-in-the-middle attack. To do that for a self-signed certificate, we need the relevant details to make that validation.
FWIW, if you find this stuff to be a bit complex to set up, I have a TrustManagerBuilder
in my CWAC-Security library that can help a bit.
android studio: https self signed certificate not trusted
So I figured it out, altough i did enable self signed certificate on android studio, I didnt enable them on kotlin, so the error came from kotlin and not android studio, a quick copy-paste from this answer
has solved it, altough I dont understand a thing from it, and if someone could send me a refrence to some sort of explantion or a tutorial for it that would be wonderful.
Setting up an HTTPS connection on Android with a self signed certificate from an AWS server
Heres how I got the certificate, although this answer may not be very helpful to others. I asked the server admin for it and he gave it to me. I believe he generated the certificate from some bash code while he was SSHed into the server. I then created an assets
folder in main
and drop the certificate file in there. I got the input stream with this line of code InputStream in = context.getAssets().open("my_cert.crt")
.
HTTPS with Self-Signed SSL Certificate Issues... Solution or better way?
I found two great examples of how to accept self-signed SSL certificates, one each for HttpsURLConnection and HttpClient.
HttpsURLConnection solution: Https Connection Android
HttpClient solution: Self-signed SSL acceptance on Android
Related Topics
Countdowntimer in Minutes and Seconds
Start a Jar File Like Service in Linux
How to Create a Directory in Java
Java: (String[])List.Toarray() Gives Classcastexception
Java Datetimeformatterbuilder Fails on Testtime
Gmail Rest API:400 Bad Request + Failed Precondition
Is It Expensive to Use Try-Catch Blocks Even If an Exception Is Never Thrown
How to Convert a .Jar to an .Exe
Converting a String to an Integer on Android
How to Debug Java -Jni Using Gdb on Linux
Difference Between _Java_Options, Java_Tool_Options and Java_Opts
How to Access an Iteration-Counter in Java's For-Each Loop
Calling One Jframe from Another Using Timer Without Any Buttons