Implementierung der zweistufigen Authentifizierung in Java

Overview Ich wollte schon immer eine zweistufige Authentifizierung implementieren, aber es war einfacher als erwartet, da es eine gute Bibliothek gab.

GoogleAuth (serverseitige Bibliothek für die zweistufige Authentifizierung)

https://github.com/wstrange/GoogleAuth

GoogleAuth ist eine serverseitige Java-Bibliothek, die ein zeitbasiertes Einmalkennwort (TOTP) erstellt, wie in RFC6238 definiert.

Wenn Sie die Serverseite mithilfe der oben genannten Bibliothek implementieren, können Sie den Benutzer mithilfe des einmaligen Tokens authentifizieren, das von einer von Google bereitgestellten Anwendung wie Google Authenticator ausgestellt wurde.

Google Authenticator für iOS

https://itunes.apple.com/jp/app/google-authenticator/id388497605?mt=8

Android-Version Google Authenticator

https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=ja

Google Authenticator kann auch verwendet werden, da ein einmaliges Token gemäß den TOTP-Spezifikationen erstellt wird.

Allgemeiner Ablauf der zweistufigen Zertifizierung

Ich denke, der Fluss wird wie folgt sein.

two-factor-auth-seq.png

Beispielcode

https://github.com/yuizho/two-factor-auth-sample

Dies ist der Implementierungscode des Serverteils im obigen Sequenzdiagramm.

Die Sprache verwendet Java.

Das Speichern von Benutzerinformationen wird durch die Verwendung von Singletons Map anstelle von DB betrogen.

Beispielcode-Erklärung

Es geht mehr um die Verwendung der Bibliothek (Google Auth) als um die Erläuterung des Beispielcodes.

SecretKey ausgeben und speichern

Sie können einen geheimen Schlüssel für "user_id" mit dem folgenden Code ausgeben und in einer Datenbank speichern.

GoogleAuthenticator gAuth = new GoogleAuthenticator();
GoogleAuthenticatorKey key = gAuth.createCredentials("user_id");

Bevor Sie den obigen Code ausführen, müssen Sie die folgenden Vorbereitungen treffen.

Bereiten Sie eine Implementierungsklasse für ICredentialRepository vor

Wenn Sie die oben genannten createCredentials ausführen, ruft GoogleAuth die saveUserCredentials-Methode der Implementierungsklasse von ICredentialRepository auf, um den secretKey zu speichern.

public class MyCredentialRepository implements ICredentialRepository {
    // ...
    @Override
    public void saveUserCredentials(String userId, String secretKey, int validationCode, List<Integer> scratchCodes) {
        //Beschreiben Sie den Vorgang zum Speichern des secretKey mit userId als Schlüssel
    }
}

ScratchCodes ist übrigens ein Code, der verwendet wird, wenn der Benutzer das Terminal verliert, und es scheint, dass standardmäßig 5 ausgegeben werden. https://github.com/wstrange/GoogleAuth#scratch-codes

Ich konnte nicht genau verstehen, wofür der Validierungscode gedacht war (ähnlich wie bei ScratchCodes?). Wenn Sie wissen, lehren Sie mich bitte: Bogen:

Ich habe es im Beispielcode nicht getan, aber ich denke, es ist eine gute Idee, die Verarbeitung dieser Werte nach Bedarf zu implementieren.

Vorbereitung für Java Service Loader

GoogleAuth implementiert ICredentialRepository mithilfe der Java ServiceLoader-API, wenn createCredentials ausgeführt wird. Holen Sie sich die Klasse und speichern Sie den secretKey.

Erstellen Sie einen META-INF / services-Ordner an einem Speicherort, an dem der Klassenpfad übergeben wird, z. B. unter src / resource, und erstellen Sie eine Textdatei mit dem Namen com.warrenstrange.googleauth.ICredentialRepository.

Wenn Sie den Namen der Implementierungsklasse von ICredentialRepository in der erstellten Datei wie folgt beschreiben, verwendet Google Auth diese Klasse.

io.github.yuizho.twofactorauth.MyCredentialRepository

Rückgabe geheimer Informationen

Generieren Sie beim Laden geheimer Informationen einschließlich des generierten secretKey in Google Authenticator einen URI im folgenden Format und konvertieren Sie ihn in QR-Code.

otpauth://totp/<userId>?secret=<secretKey>&issuer=<applicationName>

e.g. otpauth://totp/test_user?secret=ZYWAZKOQLG3YHBSZ&issuer=two-factor-auth-sample

Einzelheiten zum URI-Format finden Sie weiter unten. https://github.com/google/google-authenticator/wiki/Key-Uri-Format

Token-Überprüfung

Sie können den secretKey für "user_id" wie unten beschrieben vom Speicherziel abrufen, ein Token generieren und prüfen, ob es mit dem übergebenen Token übereinstimmt (das mit Google Authenticator erhalten wurde).

GoogleAuthenticator gAuth = new GoogleAuthenticator();
boolean isCodeValid = gAuth.authorizeUser("user_id", token);

Zu diesem Zeitpunkt ruft GoogleAuth die getSecretKey-Methode der Implementierungsklasse von ICredentialRepository auf, um den secretKey auf dieselbe Weise wie beim Speichern des secretKey abzurufen.

public class MyCredentialRepository implements ICredentialRepository {
    // ...
    @Override
    public String getSecretKey(String userId) {
        //Implementierte den Prozess, bei dem secretKey mit userId als Schlüssel aus der Tabelle abgerufen und zurückgegeben wird
    }
}

Danach wird ein Token basierend auf dem von Google Auth erfassten geheimen Schlüssel und dem aktuellen Zeitstempel generiert und mit dem Token verglichen, das an das zweite Argument von GoogleAuthenticator # authorizeUser übergeben wurde.

Zusammenfassung

Daher war es relativ einfach, eine zweistufige Authentifizierung zu implementieren.

Dieses Mal wird GoogleAuth für die serverseitige Bibliothek verwendet, aber Sie können es natürlich selbst implementieren, ohne die Bibliothek zu verwenden.

In diesem Fall sollten Sie den Token-TOTP-Generierungsprozess implementieren, während Sie auf den folgenden RFC usw. verweisen (Beispielcode ist ebenfalls verfügbar). https://tools.ietf.org/html/rfc6238

Recommended Posts

Implementierung der zweistufigen Authentifizierung in Java
Implementieren Sie die Standardauthentifizierung in Java
Implementieren Sie eine Kombination aus Mathematik in Java
2 Implementieren Sie eine einfache Syntaxanalyse in Java
Implementieren Sie das Senden von E-Mails in Java
Implementieren Sie eine funktionsähnliche schnelle Sortierung in Java
Zweistufige Zertifizierung JAVA Realization (TOTP)
Implementieren Sie rm -rf in Java.
Implementieren Sie die XML-Signatur in Java
Implementieren Sie einen tabellengesteuerten Test in Java 14
3 Implementieren Sie einen einfachen Interpreter in Java
Implementieren Sie reCAPTCHA v3 in Java / Spring
Implementieren Sie die PHP-Implodierungsfunktion in Java
Versuchen Sie, Yuma in Java zu implementieren
1 Implementieren Sie eine einfache Phrasenanalyse in Java
So implementieren Sie die Datumsberechnung in Java
So implementieren Sie den Kalman-Filter mit Java
Implementieren Sie API Gateway Lambda Authorizer in Java Lambda
Partisierung in Java
Versuchen Sie, n-ary Addition in Java zu implementieren
Änderungen in Java 11
Janken in Java
So erzwingen Sie Codierungskonventionen in Java
Implementieren Sie so etwas wie einen Stack in Java
Umfangsrate in Java
FizzBuzz in Java
Lesen Sie JSON in Java
Interpreter-Implementierung durch Java
Machen Sie einen Blackjack mit Java
Janken App in Java
Einschränkungsprogrammierung in Java
Setzen Sie Java8 in Centos7
NVL-artiger Typ in Java
Verbinden Sie Arrays in Java
"Hallo Welt" in Java
Aufrufbare Schnittstelle in Java
Azure funktioniert in Java
Formatieren Sie XML in Java
Einfache HTML-Spezialchars in Java
Boyer-Moore-Implementierung in Java
Hallo Welt in Java
Verwenden Sie OpenCV mit Java
WebApi-Memorandum mit Java
Typbestimmung in Java
Befehle in Java ausführen (Ping)
Verschiedene Threads in Java
Implementierung der Heap-Sortierung (in Java)
Zabbix API in Java
ASCII-Kunst in Java
Listen in Java vergleichen
POST JSON in Java
Fehler in Java ausdrücken
Implementieren Sie CustomView im Code
Erstellen Sie JSON in Java
Datumsmanipulation in Java 8
Was ist neu in Java 8?
Verwenden Sie PreparedStatement in Java
Was ist neu in Java 9,10,11
Parallele Ausführung in Java