Overview Ich wollte schon immer eine zweistufige Authentifizierung implementieren, aber es war einfacher als erwartet, da es eine gute Bibliothek gab.
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.
https://itunes.apple.com/jp/app/google-authenticator/id388497605?mt=8
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.
Ich denke, der Fluss wird wie folgt sein.
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.
Es geht mehr um die Verwendung der Bibliothek (Google Auth) als um die Erläuterung des Beispielcodes.
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.
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.
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
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
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.
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