preface

This blog post is a summary of the work. The knowledge points recorded temporarily are as follows: In this article, I will give you some tips on how to use OpenSSL to generate certificates that are not authenticated (mainly for common practice). Tomact and Nginx configure partial forwarding for HTTPS, and how to add SSL authentication in the background of Android requests. This article will take about 20 minutes.

1 the HTTPS humble opinion

HTTPS is equivalent to the Secure version of HTTP. SSL is added to HTTP. SSL is responsible for security.

Main Functions of SSL

  1. Authenticate users and servers to ensure that data is sent to the correct client and server; (Verify the certificate)
  2. Encrypting data to prevent data theft; (encryption)
  3. Maintain data integrity and ensure that data is not changed during transmission. (Summary algorithm)

HTTPS process

HTTPS requires a handshake between the client (browser) and the server (website) before data transmission. During the handshake, the password information for encrypting the transmitted data is established.

  1. The boss paid me for the digital certificate (the company has no money, I think of their own…)
  2. Authority-issued digital Certificates (Locally generated certificates using OpenSSL)
  3. Deploy a digital certificate on the server (locally configured in Nginx)
  4. Client request
  5. The server generates an asymmetrically encrypted key pair and sends the public key to the client
  6. The client receives the public key, generates a random number as the key shown in the figure above, and encrypts the key with the public key just received
  7. The client sends it to the server. (My son took my key)
  8. The server receives the encrypted key and decrypts it with the asymmetric private key generated locally in the first step to obtain the real key. (I lost you get the key come on come on)
  9. Then client and server with this stick wrong.. Key together to do gay. -,-

The above content is my humble opinion if there is wrong also hope to point out, thank you. (Where’s my knife…)

2openSSL generates a digital certificate

2.1 installation Openssl

Download at slproweb.com/products/Wi… (Download and install the 32-bit or 64-bit version based on the system).

2.2 Configuring environment Variables

Variable name: OPENSSL_HOME variable value: C:\ openSSL-win64 \bin; (the variable value is where openSSL is installed) Add the following at the end of the path variable: %OPENSSL_HOME%;

2.3 Creating a Private Key

First, create an SSL folder in the nginx installation directory to store files related to digital certificates. Right-click on the current folder and open the command line.

Run the openssl genrsa -des3 -out ds.key 1024 command, as shown in the following figure:

Then you’ll notice that there’s a.key file in the folder

2.4 Creating a CSR Certificate

Run the following command on the command line: openssl req -new -key ds.key -out ds. CSR (key file is the generated file, ds is the custom file name)The key file is the generated file. After the preceding command is executed, you need to enter a series of information. The most important piece of information to enter is the Common Name, for example, IF I enter localhost. Anything else you want to fill in.

2.5 Removing a Password

Remove the required password when loading ssl-supported Nginx and using the above private key, otherwise the password will be required when Nginx is started. Copy ds.key and name it ds.copy.key. On the cli, run the following command to delete the password: openssl rsa -in ds.copy.key -out ds.key

2.6 Generating a CRT Certificate

openssl x509 -req -days 365 -in ds.csr -signkey ds.key -out ds.crt

After the above steps, we can get 4 files, we will mainly use the key and CRT files.

Now that openSSL is done generating the digital certificate we need,

3 tomact nginx Configures HTTPS

Many articles found on the Web describe how SSL support must be configured on both Nginx and Tomcat to enable HTTPS support for Nginx + Tomcat. But the solution I provide for configuration is HTTPS communication between the browser and Nginx, and a normal HTTP connection between Nginx and Tomcat via proxy_pass.

3.1 NGINx Configuration modification

My file is in the C:\nginx\conf directory. Open the nginx.conf file in any editor (such as Sublime Text)

Server {# default HTTP port 80, default HTTPS port 443 listen 443 SSL; server_name localhost; # address here is me the address of the server, your own path to the file to fill in / / symbol ssl_certificate C: / / dsPulse / / SSL / / test. The CRT. ssl_certificate_key C://dsPulse//ssl//test.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:! aNULL:! MD5; ssl_prefer_server_ciphers on; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Proto https; proxy_redirect off; proxy_connect_timeout 240; proxy_send_timeout 240; proxy_read_timeout 240; My tomact address proxy_pass http://127.0.0.1:8080; }}Copy the code

Ssl_certificate and SSL_Certificate_key are the most critical configurations. Configure the other configurations as normal. Proxy_set_header x-forwarded-proto HTTPS; configuration

3.2 tomact modify

Find the tomact installation path and find the configuration file server file



      
<Server port="8005" shutdown="SHUTDOWN">
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP / 1.1"
               connectionTimeout="20000"
               redirectPort="443"
               proxyPort="443"/>
 
    <Engine name="Catalina" defaultHost="localhost">
 
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <! -- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html -->
        <! -- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> -->

        <! -- Access log processes all example. Documentation at: /docs/config/valve.htmlNote: The pattern used is equivalent to using pattern="common" -->
	`	<Valve className="org.apache.catalina.valves.RemoteIpValve"
                  remoteIpHeader="x-forwarded-for"
                  remoteIpProxiesHeader="x-forwarded-by"
                  protocolHeader="x-forwarded-proto"
            />
      </Host>
    </Engine>
    </Engine>
  </Service>

Copy the code

However, it is important to note that proxyPort= “443”, which is the key to this article, and of course redirectPort must also be 443. Node configuration is also very important

After modifying tomAct, start TomAct to start Nginx. The nginx command is recommended

Start nginx # to start nginx

Nginx. exe -s quit # Reload nginx.exe -s reload # reload nginx.exe -s reload # reload nginx This command is used when the configuration information is modified and needs to be reloaded. Nginx. exe -s reopen # Reopen the log file nginx -v # Check the nginx version

For successful startup or failure, check the nginx/ log /log file to see if there is an error, if successful log package will have a nginx.pid file. You can also use Postman mock access to test the success of the configuration.

4 Modifying the Android code

First of all, the web plugin I use on Android is OKHTTP. Of course, if you use Retofit, it’s the same thing.

If you do not want to take the data out, you can also create a new raw folder under the Android project directly. For detailed operations, see Carry forward blog: Carry forward HTTPS

Below is the okHTTP util section of my project

private OkHttpClient.Builder builder;
    private OkHttpClient client;
    private static MyOkHttp instance;

    private static final String SSL_KEY = "Own key string";

    public MyOkHttp(a) {
        builder = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS)
                .connectTimeout(8, TimeUnit.SECONDS)
                .writeTimeout(8, TimeUnit.SECONDS);
        SSLSocketFactory sslSocketFactory = getSSLSocketFactory(new Buffer().writeUtf8(SSL_KEY).inputStream());
        if(sslSocketFactory ! =null) {
            builder.sslSocketFactory(sslSocketFactory);
        };
        builder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                // Enforce certificate security
                return true; }}); client = builder.build(); }/** * SSL factory class *@param certificates certificates
     * @return SSLSocketFactory
     */
    private static SSLSocketFactory getSSLSocketFactory(InputStream... certificates) {
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            int index = 0;
            for (InputStream certificate : certificates) {
                String certificateAlias = Integer.toString(index++);
                keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));

                try {
                    if(certificate ! =null){ certificate.close(); }}catch (IOException e) {
                }
            }

            SSLContext sslContext = SSLContext.getInstance("TLS");

            TrustManagerFactory trustManagerFactory =
                    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

            trustManagerFactory.init(keyStore);
            sslContext.init
                    (
                            null,
                            trustManagerFactory.getTrustManagers(),
                            new SecureRandom()
                    );
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

Copy the code

SSLSocketFactory = getSSLSocketFactory(new Buffer().writeuTF8 (SSL_KEY).inputStream()); In this line, the buffer is in okio, and the SSLSocketFactory is obtained from the factory class. Then builder. SslSocketFactory (sslSocketFactory); Of course, these Settings are basically ok. However, since my SSL is generated by myself, if my SSL is the same as mine, I need to add HostnameVerifier to force the certificate to be set as secure. If your SSL is issued by an authority, you do not need to bother.

In addition, due to the mixed use of the project, there is a white screen problem when loading the HTTPS interface through webView. Here is the solution (as of July 26, 2018 17:41:15) :

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // Allow it to load mixed Network protocol content (HTTP HTTPS)
            webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
webview.setWebViewClient(new WebViewClient() {
            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                // Receive certificate (openSSL generates its own certificate)handler.proceed(); }}Copy the code

Above the code has been commented very clear, starved to add class slip, this article is relatively basic, only used to record their own development experience and knowledge sharing, if you find that I write wrong there, please correct, I will actively listen to my knife (:зゝ∠) of course I will take my knife (:зゝ∠)…