How to Use Https for Android
How does Android Use Https?
NoHttp is a framework dedicated to Android Network request and download.
This article is important in the NoHttp series. Let's introduce it to you:
What is Https?
HTTPS (Hyper Text Transfer Protocol over Secure Socket Layer) is an HTTP channel designed for security. It is simply a Secure version of HTTP. That is, the SSL layer is added under HTTP. The Security Foundation of HTTPS is SSL, so the detailed content of encryption requires SSL. It is a URI Scheme (Abstract identifier system) with syntaxes similar to Http: system. Secure HTTP data transmission. Https: the URL indicates that HTTP is used, but HTTPS has a default port different from HTTP and an encryption/authentication layer (between HTTP and TCP ). The system was initially developed by NetScape and built into its browser Netscape Navigator, providing authentication and encrypted communication methods. It is now widely used in secure and sensitive communications on the World Wide Web, such as finance, online shopping, and other payment-related fields.
This is not an installation plan. Let's look at it in a simple way.First, let's talk about the original Https, and then how the framework uses Https in one sentence.
How to Use Https for the original Java code of Android
First, let's popularize how Android uses the original java code to request the network.
Android is developed in Java. The http APIs provided by Java include:HttpURLConnection
, Added to the Android systemApache Httpclient
And laterHttpClient
Google deleted the SDK, so we do not recommend using HttpClient for network requests, so here we only listHttpURLConnection
.
Step 1: open a connection to an address
Here we open my blog address and use the GET method to request
URL url = new URL("http://blog.csdn.net/yanzhenjie1003");HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();urlConnection.setRequestMethod("GET");
Step 2: Determine whether it is an Https request and set SSLSocketFactory
For Https requests, perform security verification and other operations.SSLSokcetFactory
There are two methods: one is to include the Https certificate, the other is to allow Https requests directly without a certificate, and the other isSSLContext
Here:
// Set sslsocketfoacloud. There are two types: 1. security certificate required 2. no security certificate is required; check the official website and go down to if (urlConnection instanceof HttpsURLConnection) {// Https requests SSLContext sslContext = SSLContextUtil. getSSLContext (); if (sslContext! = Null) {SSLSocketFactory sslSocketFactory = sslContext. getSocketFactory (); (HttpsURLConnection) urlConnection). setSSLSocketFactory (sslSocketFactory );}}
SoSSLContext
How to generate the certificate? haha, don't worry. Let's finish the request process first, and load the certificate later.
Step 3: Set required properties
// Set the attribute urlConnection. setConnectTimeout (8*1000); urlConnection. setReadTimeout (8*1000 );
Step 4: Read data, send it to the main thread, and disconnect
Int responseCode = urlConnection. getResponseCode (); if (responseCode = 200) {// The request is successful. InputStream inputStream = urlConnection. getInputStream (); // read the result and send it to the main thread... inputStream. close ();} urlConnection. disconnect ();
Complete code
URL url = new URL ("http://blog.csdn.net/yanzhenjie1003"); HttpURLConnection urlConnection = (HttpURLConnection) url. openConnection (); urlConnection. setRequestMethod ("GET"); // set sslsocketfoacloud. There are two types: 1. security certificate required 2. no security certificate is required; check the official website and go down to if (urlConnection instanceof HttpsURLConnection) {// Https requests SSLContext sslContext = SSLContextUtil. getSSLContext (); if (sslContext! = Null) {SSLSocketFactory sslSocketFactory = sslContext. getSocketFactory (); (HttpsURLConnection) urlConnection ). setSSLSocketFactory (sslSocketFactory) ;}// set the attribute urlConnection. setConnectTimeout (8*1000); urlConnection. setReadTimeout (8*1000); int responseCode = urlConnection. getResponseCode (); if (responseCode = 200) {// The request is successful. InputStream inputStream = urlConnection. getInputStream (); // read the result and send it to the main thread... inputStream. close ();} urlConnection. disconnect ();
In this way, the entire request is completed. In fact, the Android request network is just a little bit of code. Then we need to write more code, encapsulate the write parameters, and fault tolerance is a small framework. Is it easy?
How to play Https with the popular NoHttp framework
It is not too simple to use NoHttp. It takes only one or two sentences to transmit parameters, files, downloads, and so on.
Request
Request = NoHttp. createStringRequest (url, RequestMethod. POST); // note that the code for setting SSLSokcetFactory here is the same SSLContext sslContext = SSLContextUtil. getSSLContext (); if (sslContext! = Null) {SSLSocketFactory socketFactory = sslContext. getSocketFactory (); httpsRequest. setSSLSocketFactory (socketFactory); requestQueue. add (0, request, httpListener); // add to request queue, waiting for receiving result}
We noticed that the code for setting the Socket above is the same, and the rest is a new request object. Is it simpler than native?
This framework is called NoHttp and is an open-source network framework for Android.
How does SSLSocketFactory object come from?
The above is used in both pure Android code and NoHttp frameworkSSLContext
This guy is responsible for Certificate Management and trust manager. We can say that Https can have or have no certificate. Let's look at these two situations.
SSLContext with security certificate
We put the Https certificate under the assets Directory and load it through the stream:
Public static SSLContext getSSLContext () {// generate SSLContext object SSLContext sslContext = SSLContext. getInstance ("TLS"); // load certificate InputStream inStream = Application from assets. getInstance (). getAssets (). open ("srca. cer "); // certificate factory CertificateFactory cerFactory = CertificateFactory. getInstance ("X.509"); Certificate cer = cerFactory. generateCertificate (inStream); // KeyStore kStore = KeyStore. getInstance ("PKCS12"); kStore. load (null, null); kStore. setCertificateEntry ("trust", cer); // load the certificate to the keystore // key manager KeyManagerFactory keyFactory = KeyManagerFactory. getInstance (KeyManagerFactory. getDefaultAlgorithm (); keyFactory. init (kStore, null); // load the keystore to the Manager // trust manager TrustManagerFactory tFactory = TrustManagerFactory. getInstance (TrustManagerFactory. getDefaultAlgorithm (); tFactory. init (kStore); // load the keystore to the trust manager // initialize sslContext. init (keyFactory. getKeyManagers (), tFactory. getTrustManagers (), new SecureRandom (); return sslContext ;}
In the last sentencenew SecureRandom()
There were bugs in the system before Android4.4.
Fixed the SecureRandom Bug in Android.
Apache Harmony 6.0M3 and SecureRandom implementations used in Java encryption architecture (JCA) earlier than Android 4.4 have security vulnerabilities.classlib/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java
FileengineNextBytes()
Method. When the user does not provide a seed to generate a random number, the program cannot adjust the offset correctly, resulting in prediction of the process in which the pseudo-random number generator (PRNG) generates a random sequence.
But the NoHttp internal bug has been fixed. If you want to write the framework yourself, I am afraid you need to write a lot of code to fix this problem. Therefore, we recommend that you use NoHttp.
SSLContext without security certificate
The above shows that you need to generate SSLContext for the security certificate, and then you do not need the certificate request. You need two objects, one isSSLContext
(As explained above); the other isHostnameVerifier
As the name implies, it means that the host name matches. Let's look at the code.
public static SSLContext getSLLContext() { SSLContext sslContext = null; try { sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }}, new SecureRandom()); } catch (Exception e) { e.printStackTrace(); } return sslContext;}
In this case, you only need to pass a null Certificate Manager to drink a default trust manager.
Next let's take a look.HostnameVerifier
Since it is the host name verification, we directly pass:
private static HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; }};
How can this be used? In Android native code usage, obtainSSLContext
The method names are different.setHostnameVerifier
, The others are the same as those used with security certificates:
URL url = new URL ("http://blog.csdn.net/yanzhenjie1003"); HttpURLConnection urlConnection = (HttpURLConnection) url. openConnection (); urlConnection. setRequestMethod ("GET"); // set sslsocketfoacloud. There are two types: 1. security certificate required 2. no security certificate is required; check the official website and go down to if (urlConnection instanceof HttpsURLConnection) {// Https requests SSLContext sslContext = SSLContextUtil. getSSLContext (); if (sslContext! = Null) {SSLSocketFactory sslSocketFactory = sslContext. getSLLContextNoCertificate (); (HttpsURLConnection) urlConnection ). setSSLSocketFactory (sslSocketFactory); (HttpsURLConnection) urlConnection ). setHostnameVerifier (SSLContextUtil. hostnameVerifier) ;}}// set the urlConnection attribute. setConnectTimeout (8*1000); urlConnection. setReadTimeout (8*1000); int responseCode = urlConnection. getResponseCode (); if (responseCode = 200) {// The request is successful. InputStream inputStream = urlConnection. getInputStream (); // read the result and send it to the main thread... inputStream. close ();} urlConnection. disconnect ();
NoHttp usage, the Code is the same as the above NoHttp load certificate, an additional sentencesetHostnameVerifier
Of:
Request
Request = NoHttp. createStringRequest (url, RequestMethod. POST); SSLContext sslContext = SSLContextUtil. getSSLContext (); if (sslContext! = Null) {SSLSocketFactory socketFactory = sslContext. getSLLContextNoCertificate (); httpsRequest. setSSLSocketFactory (socketFactory); httpsRequest. setHostnameVerifier (SSLContextUtil. hostnameVerifier); requestQueue. add (0, request, httpListener); // add to request queue, waiting for receiving result}