[JAVA] Verwenden Sie das pfx-Zertifikat mit Okhttp3

Postscript-Geschichte

2020/02/08 Referenzlink hinzugefügt 2020/02/10 Der Grund für die asynchrone Verwendung wurde hinzugefügt

Einführung

Behalten Sie den Code bei, den Sie geschrieben haben, als Sie beschlossen haben, die HTTPS-Kommunikation mithilfe des Client-Zertifikats als Notiz zu unterstützen, falls Sie das Unternehmen verlassen und den Quellcode nicht sehen können Der Grund, warum ich bei Okhttp bleibe, ist, dass ich es hasste, weil ich vor langer Zeit gelitten habe. Http (s) URLConnection Es mag einige Teile geben, die beim Schreiben schlampig sind, und einige Teile, die wie eine Predigt für die aktive Person sind, aber bitte vergib mir.

Vorbereitungen

  1. Erstellen Sie einen Ordner "Assets" unter main (dieselbe Ebene wie main und res).
  2. Speichern Sie das pfx-Zertifikat im Assets-Ordner (diesmal verwenden Sie zur Vereinfachung "hogehage.pfx").
  3. Fügen Sie "AndroidManifest.xml" die Berechtigung zur Internetkommunikation hinzu (↓ wie folgt) Es ist kein Problem, wenn sich der zusätzliche Platz zwischen Manifesten befindet, aber nicht zwischen Aktivitäten geschrieben wird
<Manifest ・ ・ ・
...
//Berechtigungen für die Internetverbindung
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
  1. Fügen Sie dem Teil "Abhängigkeiten" von "build.gradle (unter App)" Folgendes hinzu: " Die Version ist 2020/02/05 Überprüfen Sie den Teil "Releases" von https://square.github.io/okhttp/, um festzustellen, ob es sich um den neuesten handelt

build.gradle


・ ・ ・
dependencies {
・ ・ ・
implementation("com.squareup.okhttp3:okhttp:4.3.1")

1 und 2 sind für die HTTPS-Kommunikation, 3 und 4 sind für Okhttp Bisher wird es schwieriger zu schreiben ... FE Fukayuki 〇 Ich möchte es tun

Code

Asynctask, nicht der Hauptthread ... Ich schreibe in der sogenannten asynchronen Verarbeitung Ich habe früher im Haupt-Thread (MainActivity usw.) geschrieben, aber ... das? Warum hast du es geändert? → Ursprünglich verwendete Asynctask die Httpurl-Verbindung. Ich habe versucht, okhttp asynchron zu verwenden, und es war möglich, und die Bedienung der Anwendung scheint einfacher zu sein. Deshalb habe ich sie so übernommen, wie sie ist (zusätzlicher Hinweis).

AsyncHttps.java


package com.example.test;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

//Asynchrone Verarbeitung
//Ein Ort für die HTTPS-Kommunikation
//Der Aufrufer konvertierte das Bild in ein Byte-Array und übergab es an diesen Vorgang
public class AsyncHttps extends AsyncTask<byte[], Void, String>
{

    private Context mContext;
    public AsyncHttps(Context context)
    {mContext = context;}

    public static String res=null;

    final Handler handler = new Handler();
    //Für Array-Nummern in URLsList
    public static int url_id = 0;

    //Speichervariable für Kommunikationsergebnisse
    public static String result = null;

    //Asynchrone Verarbeitung
    @Override
    protected String doInBackground(byte[]... params)
    {

        //Mir wurde klar, dass ich die URL-Liste in einem anderen Bereich als Array schreiben und die Array-Nummer an die Quelle senden sollte.
        String urlSt = URLsList.URL[url_id];

        byte[] word = params[0];

	//
        return result;
    }


    //Für die http-Kommunikation
    public void http_post(byte[] bytes)
    {
        //Es scheint eine Einstellung für das Senden mit JSON zu sein
	//MediaType muss entsprechend Ihrer Sendung geändert werden(Wenn es ein Bild ist"image/jpg"Fühle mich wie)
        MediaType mediaType= MediaType.parse("application/json; charset=utf-8");
        //Körpererstellung anfordern. Dinge zu senden
        RequestBody requestBody = RequestBody.create(mediaType,bytes);
        //Es ist wie eine Anfrage zu stellen und Post zu packen, oder?(Texto)
        Request request = new Request.Builder()
                //Ziel
                .url(URLsList.URL[url_id])
                .post(requestBody)      //Inhalt zu senden
                .build();               //Bauen Sie diese auf


        KeyManagerFactory keyManagerFactory;
        //Kennwort beim Erstellen des Zertifikats festgelegt
        final char[] PASSWORD = "***Passwort hier***".toCharArray();
        InputStream inputStream;
        TrustManagerFactory trustManagerFactory;
        SSLSocketFactory sslSocketFactory;
        X509TrustManager trustManager;
        try
        {
            //Angeben der Client-Zertifikatdatei(Legen Sie es in den Assets-Ordner)
            inputStream = mContext.getResources().getAssets().open("hogehage.pfx");
            //Als Referenz war diese Erweiterung p12, ist das nicht der Fall?
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            //Von hier an können Sie kopieren und einfügen, ohne an etwas zu denken
            keyStore.load(inputStream,PASSWORD);
            trustManagerFactory = TrustManagerFactory.getInstance
                    (TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager))
            {
                throw new IllegalStateException("Unexpected default trust managers:"
                        + Arrays.toString(trustManagers));
            }
            trustManager = (X509TrustManager)trustManagers[0];

            keyManagerFactory = KeyManagerFactory.getInstance("X509");
            keyManagerFactory.init(keyStore,PASSWORD);
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(keyManagerFactory.getKeyManagers(),null,null);
            sslSocketFactory = sslContext.getSocketFactory();
            //Bisher kopieren und einfügen

            final OkHttpClient client = new OkHttpClient.Builder()
                    //.connectTimeout(10, TimeUnit.SECONDS)	//Timeout Einstellung 3 Schütze
                    //.readTimeout(10, TimeUnit.SECONDS)	//Ich weiß nicht, was Sie einstellen
                    //.writeTimeout(10, TimeUnit.SECONDS)	//Bis später
                    .sslSocketFactory(sslSocketFactory,trustManager)
                    .build();

            client.newCall(request).enqueue(new Callback()
            {
                @Override
                public void onFailure(@NonNull Call call, IOException e)
                {
                    //Es scheint, dass die Verarbeitung, wenn eine Ausnahme auftritt, stabil ist, wenn sie separat verarbeitet wird.
                    failMessage();
                    e.printStackTrace();
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException
                {
                    result = String.valueOf(response);
                    //Wenn etwas zurückkommt, kann ich hier etwas tun oder auch nicht
                    client.connectionPool().evictAll();
                }
            });
        }catch (IOException e)//Wenn darunter etwas explodiert, wird es im Protokoll der Registerkarte Fehler angezeigt. Es gibt nichts zu berühren.
        {Log.e("Fehlerinhalt:", String.valueOf(e));}
        catch (NoSuchAlgorithmException e)
        {Log.e("Fehlerinhalt:", String.valueOf(e));}
        catch (CertificateException e)
        {Log.e("Fehlerinhalt:", String.valueOf(e));}
        catch (UnrecoverableKeyException e) 
        {Log.e("Fehlerinhalt:", String.valueOf(e));}
        catch (KeyStoreException e) 
        {Log.e("Fehlerinhalt:", String.valueOf(e));}
        catch (KeyManagementException e) 
        {Log.e("Fehlerinhalt:", String.valueOf(e));}
    }

    //Wenn eine Ausnahme auftritt(Wenn etwas schief geht)wird bearbeitet
    private void failMessage()
    {Log.d("Kommunikationsergebnis:","ich hab es nicht ausgearbeitet…");}

}

Referenz

Okhttp Offiziell: https://square.github.io/okhttp/ Client-Zertifikat-Authentifizierung in der Android-App: https://qiita.com/c_ume/items/d082ffd20b3316aab805 Now that SSLSocketFactory is deprecated on Android, what would be the best way to handle Client Certificate Authentication? https://stackoverflow.com/questions/31002159/now-that-sslsocketfactory-is-deprecated-on-android-what-would-be-the-best-way-t

Recommended Posts

Verwenden Sie das pfx-Zertifikat mit Okhttp3
Verwenden Sie ProGuard mit Gradle
Verwenden Sie Puphpeteer mit Docker
Verwenden Sie XVim2 mit Xcode 12.0.1
Verwenden von CentOS mit LXD
Verwenden Sie Webmock mit Rspec
Verwenden Sie WebJars mit Gradle
Verwenden Sie jlink mit gradle
Verwenden Sie Lambda-Ebenen mit Java
Verwenden Sie GDAL mit Python mit Docker
Verwenden Sie Thymeleaf mit Azure-Funktionen
Verwenden Sie die Bulk-API mit RestHighLevelClient
Verwenden Sie SDKMAN! Mit Git Bash
Verwenden Sie mit Rails 6.0 mehrere Datenbanken
Verwenden Sie Spring JDBC mit Spring Boot
Verwenden Sie Ruby mit Google Colab
Verwenden Sie SpatiaLite mit Java / JDBC
Verwenden Sie log4j2 mit YAML + Gradle
[Docker] Wird immer mit Docker + Rails verwendet
Verwenden Sie PlantUML mit Visual Studio Code
Verwenden Sie die Standardauthentifizierung mit Spring Boot
Verwenden Sie Java mit MSYS und Cygwin
Verwenden Sie den Konstruktor mit Argumenten in cucumber-picocontainer
Verwenden Sie Microsoft Graph mit Standard-Java
Verwenden Sie den PostgreSQL-Inet-Typ mit DbUnit
Verwenden Sie Bootstrap 4 mit PlayFramework 2.6 (kein CDN)
Verwenden von Git mit SourceTree und Eclipse
Verwenden Sie Azure Bing SpellCheck mit Java
Verwenden Sie JDBC mit Java und Scala.
Verwenden Sie DataDog APM mit nicht unterstützten Frameworks
Verwenden Sie Java 11 mit Google Cloud-Funktionen
Wie man mssql-tools mit alpine benutzt
Beginnend mit Spring Boot 0. Verwenden Sie Spring CLI
Verwenden von cuda11.0 mit pytorch mit Docker