it-swarm.com.de

Android Login - Account Authenticator vs Manuelle Authentifizierung

Ich bin dabei, die Anmeldung zusammen mit der Benutzerauthentifizierung in meiner App zu implementieren.

Meine erste Idee war, es manuell zu tun, Benutzername und Passwort beim Server zu registrieren, ein Authentifizierungstoken zu erhalten, es zu speichern und es bei nachfolgenden Anfragen zu verwenden.

Nachdem ich herumgegoogelt hatte, stellte ich fest, dass die richtige Vorgehensweise für Android) die Verwendung des Kontoauthentifizierers war. Ich habe einige Beispiele für dessen Implementierung gesehen, verstehe aber nicht, welchen Vorteil es hat Das liegt daran, dass mehr als ein Konto gespeichert werden kann, dass Synchronisierungsprobleme vorliegen, und ich würde mich freuen, wenn mir jemand dies erklären könnte, damit ich den Code besser verstehe und weiß, warum er was tut es ist.

35
Daniel Julio

Ich kann mehr als ein Konto gespeichert haben?

Ja. Sehen Sie, wie Google oder Facebook es machen.

Liegt es an Synchronisierungsproblemen?

Ja, Sie benötigen ein Konto, um den Synchronisationsmechanismus wie SyncAdapter zu verwenden.

Warum sollten Sie AccountAuthenticator verwenden?

  • Unterstützung von Hintergrundsynchronisationsmechanismen wie SyncAdapter;

  • Standardmethode zum Authentifizieren von Benutzern;

  • Unterstützen Sie verschiedene Token;

  • Account-Sharing mit unterschiedlichen Rechten

Was musst du tun?

1). Erstelle Authenticator;

2). Erstelle Activity für die Benutzeranmeldung;

3). Erstellen Sie Service, um mit dem Konto zu kommunizieren.

Nutzungsbedingungen.

AccountManager - verwaltet das Konto auf dem Gerät. Fordern Sie Authentifizierungstoken an, die Sie mit AccountManager verwenden sollten.

AbstractAccountAuthenticator - Komponente zum Arbeiten mit Kontotypen. Es enthält alle Logik für die Arbeit mit dem Konto (Autorisierung, Zugriffsrechte usw.). Ein AbstractAccountAuthenticator kann von verschiedenen Anwendungen verwendet werden (wie Google-Konto für Google Mail, Kalender, Laufwerk usw.).

AccountAuthenticatorActivity - base Activity, zum Autorisieren/Erstellen eines Kontos. AccountManager ruft dieses Konto auf, wenn es erforderlich ist, ein Konto zu identifizieren (Token existiert nicht oder ist abgelaufen)

Wie funktioniert das alles? Schauen Sie sich das Bild unten an:

Android account management diagram

Schritte.

1). Erstelle Authenticator;

Sie müssen AbstractAccountAuthenticator erweitern und 7 Methoden überschreiben:

  • Bundle editProperties(AccountAuthenticatorResponse response, String accountType)link
  • Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options)link
  • Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options)link
  • Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)link
  • String getAuthTokenLabel(String authTokenType)link
  • Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)link
  • Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features)link

Beispiel:

public class LodossAuthenticator extends AbstractAccountAuthenticator {

    private static final String LOG_TAG = LodossAuthenticator.class.getSimpleName();

    private final Context mContext;

    public LodossAuthenticator(Context context) {
        super(context);
        mContext = context;
    }

    @Override
    public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
        return null;
    }

    @Override
    public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
        final Intent intent = new Intent(mContext, CustomServerAuthenticatorSigninActivity.class);
        intent.putExtra(Config.ARG_ACCOUNT_TYPE, accountType);
        intent.putExtra(Config.ARG_AUTH_TYPE, authTokenType);
        intent.putExtra(Config.ARG_IS_ADDING_NEW_ACCOUNT, true);
        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);

        final Bundle bundle = new Bundle();
    bundle.putParcelable(AccountManager.KEY_INTENT, intent);
    return bundle;
    }

    @Override
    public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
        return null;
    }

    @Override
    public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
        // If the caller requested an authToken type we don't support, then
        // return an error
        if (!authTokenType.equals(AccountGeneral.AUTHTOKEN_TYPE_READ_ONLY) && !authTokenType.equals(AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS)) {
            final Bundle result = new Bundle();
            result.putString(AccountManager.KEY_ERROR_MESSAGE, "invalid authTokenType");
            return result;
        }

        // Extract the username and password from the Account Manager, and ask
        // the server for an appropriate AuthToken.
        final AccountManager am = AccountManager.get(mContext);
        String authToken = am.peekAuthToken(account, authTokenType);

        // Lets give another try to authenticate the user
        if (TextUtils.isEmpty(authToken)) {
            final String password = am.getPassword(account);
            if (password != null) {
                try {
                    authToken = sServerAuthenticate.userSignIn(account.name, password, authTokenType);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        // If we get an authToken - we return it
        if (!TextUtils.isEmpty(authToken)) {
            final Bundle result = new Bundle();
            result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
            result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
            result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
            return result;
        }

        // If we get here, then we couldn't access the user's password - so we
        // need to re-Prompt them for their credentials. We do that by creating
        // an intent to display our AuthenticatorActivity.
        final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
        intent.putExtra(com.lodoss.authlib.Config.ARG_ACCOUNT_TYPE, account.type);
        intent.putExtra(com.lodoss.authlib.Config.ARG_AUTH_TYPE, authTokenType);
        intent.putExtra(Config.ARG_ACCOUNT_NAME, account.name);
        final Bundle bundle = new Bundle();
    bundle.putParcelable(AccountManager.KEY_INTENT, intent);
    return bundle;
    }

    @Override
    public String getAuthTokenLabel(String authTokenType) {
        if (AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS.equals(authTokenType))
            return AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS_LABEL;
        else if (AccountGeneral.AUTHTOKEN_TYPE_READ_ONLY.equals(authTokenType))
            return AccountGeneral.AUTHTOKEN_TYPE_READ_ONLY_LABEL;
        else
            return authTokenType + " (Label)";
    }

    @Override
    public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
        return null;
    }

    @Override
    public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
        final Bundle result = new Bundle();
        result.putBoolean(KEY_BOOLEAN_RESULT, false);
        return result;
    }
}

Erläuterung:

Sie müssen also nur zwei Methoden anzeigen: addAccount, getAuthToken.

In addAccount habe ich einige Konfigurationsparameter hinzugefügt, die von meinem Activity für die Benutzeranmeldung verwendet werden. Der Hauptpunkt hier ist intent.putExtra(Config.ARG_ACCOUNT_TYPE, accountType); - Sie sollten hier den Kontotyp angeben. Andere Manipulationen sind nicht erforderlich.

In getAuthToken - Kommentare bitte lesen. Ich habe diese Methode aus dinicAuthenticator.Java kopiert und eingefügt

Außerdem benötigen Sie in Ihrer AndroidManifest.xml folgende Berechtigungen:

<uses-permission Android:name="Android.permission.GET_ACCOUNTS" />
<uses-permission Android:name="Android.permission.MANAGE_ACCOUNTS" />
<uses-permission Android:name="Android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission Android:name="Android.permission.USE_CREDENTIALS" />

Zusammenfassung von Methoden addAccount und getAuthToken

Versuchen Sie, ein Token abzurufen. Wenn ein Token vorhanden ist, wird das Ergebnis zurückgegeben. Anderenfalls wird Activity für die Autorisierung angezeigt

2). Erstelle Activity für die Benutzeranmeldung;

Siehe AuthenticatorActivity

Kurze Erklärung: Formular mit UserId und Passwort erstellen. Wenn Sie die Benutzer-ID- und Kennwortdaten verwenden, rufen Sie das Authentifizierungstoken vom Server ab und führen Sie dann den folgenden Schritt aus:

mAccountManager.addAccountExplicitly(account, accountPassword, null);
mAccountManager.setAuthToken(account, authtokenType, authtoken);

3). Erstellen Sie ein Service, um mit dem Konto zu kommunizieren.

Siehe dinicAuthenticatorService

Vergessen Sie nicht, diese Zeile in AndroidManifest.xml Zu Service hinzuzufügen:

    <intent-filter>
        <action Android:name="Android.accounts.AccountAuthenticator" />
    </intent-filter>
    <meta-data Android:name="Android.accounts.AccountAuthenticator"
               Android:resource="@xml/authenticator" />

Und auch in res/xml Füge die Datei authenticator.xml Hinzu:

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:Android="http://schemas.Android.com/apk/res/Android"
                       Android:accountType="com.mediamanagment.app"
                       Android:icon="@drawable/ic_launcher"
                       Android:smallIcon="@drawable/ic_launcher"
                       Android:label="@string/authenticator_label"/>

Das ist alles. Sie können Ihr AccountAuthenticator verwenden.

Für Ausgangsmaterialien dank

101
Alexander

Das AccountManager ist aus folgenden Gründen gut:

  • Zunächst müssen Sie mehrere Kontonamen mit unterschiedlichen Zugriffsebenen auf die Funktionen der App unter einem einzigen Kontotyp speichern. In einer Video-Streaming-App können beispielsweise zwei Kontonamen vorhanden sein: einer mit Demo-Zugriff auf eine begrenzte Anzahl von Videos und der andere mit monatlichem Zugriff auf alle Videos. Dies ist jedoch nicht der Hauptgrund für die Verwendung von Accounts, da Sie dies problemlos in Ihrer App verwalten können, ohne dass dieses schicke Accounts -Ding erforderlich ist….
  • Der andere Vorteil der Verwendung von Accounts besteht darin, dass die herkömmliche Autorisierung mit Benutzername und Kennwort bei jeder Anforderung einer autorisierten Funktion durch den Benutzer aufgehoben wird, da die Authentifizierung im Hintergrund stattfindet und der Benutzer nach seinem Kennwort gefragt wird nur in einem bestimmten zustand, auf den ich später noch eingehen werde.
  • Durch die Verwendung der Funktion Accounts in Android entfällt auch die Notwendigkeit, den eigenen Kontotyp zu definieren. Sie sind wahrscheinlich auf die Apps gestoßen, die Google-Konten für die Autorisierung verwendet haben. Dies erspart Ihnen den Aufwand, ein neues Konto zu erstellen und sich die Anmeldeinformationen für den Benutzer zu merken.
  • Accounts kann unabhängig voneinander über Einstellungen → Konten hinzugefügt werden
  • Die plattformübergreifende Benutzerautorisierung kann einfach mit Accounts verwaltet werden. Beispielsweise kann der Client gleichzeitig auf geschütztes Material in seinem Android Gerät und auf seinem PC zugreifen, ohne dass wiederholte Anmeldungen erforderlich sind.
  • Unter Sicherheitsaspekten ermöglicht die Verwendung des gleichen Kennworts bei jeder Anforderung an den Server das mögliche Abhören nicht sicherer Verbindungen. Die Passwortverschlüsselung reicht hier nicht aus, um einen Passwortdiebstahl zu verhindern.
  • Schließlich besteht ein wichtiger Grund für die Verwendung der Funktion Accounts in Android darin, die beiden an einem von Accounts abhängigen Geschäft beteiligten Parteien, den sogenannten Authentifikator und den Ressourcenbesitzer, voneinander zu trennen Beeinträchtigung der Anmeldeinformationen des Clients (Benutzers). Die Begriffe mögen vage erscheinen, aber geben Sie nicht auf, bis Sie den folgenden Absatz gelesen haben.

Lassen Sie mich auf Letzteres anhand eines Beispiels für eine Video-Streaming-App näher eingehen. Unternehmen A ist Inhaber eines Video-Streaming-Geschäfts im Vertrag mit Unternehmen B, um bestimmten Mitgliedern Premium-Streaming-Dienste zur Verfügung zu stellen. Firma B verwendet eine Benutzernamen- und Passwortmethode zur Erkennung des Benutzers. Damit Unternehmen A die Premium-Mitglieder von B erkennt, besteht eine Möglichkeit darin, die Liste von B abzurufen und einen ähnlichen Mechanismus zum Abgleichen von Benutzernamen und Passwort zu verwenden. Auf diese Weise sind der Authentifizierer und der Ressourcenbesitzer identisch (Firma A). Abgesehen von der Verpflichtung des Benutzers, sich ein zweites Passwort zu merken, ist es sehr wahrscheinlich, dass er dasselbe Passwort wie das Profil seines Unternehmens B für die Nutzung der Dienste von A festgelegt hat. Dies ist offensichtlich nicht günstig.

Um die oben genannten Mängel zu beseitigen, wurde OAuth eingeführt. Als ein offener Standard für die Autorisierung fordert OAuth im obigen Beispiel, dass die Autorisierung von Unternehmen B (Authentifikator) durchgeführt wird, indem ein Token mit dem Namen Access Token für die berechtigten Benutzer (Drittanbieter) ausgestellt wird und anschließend das Unternehmen bereitgestellt wird A (Ressourcenbesitzer) mit dem Token. Kein Token bedeutet also keine Berechtigung.

Ich habe mehr darüber und mehr über AccountManager auf meiner Website unter hier ausgearbeitet

7
Ali Nem

In den Android-Einstellungen haben Sie Konten für Ihren Kontotyp und können von dort aus ein Konto hinzufügen. Der AccountManager ist auch ein zentraler Ort zum Speichern von Anmeldeinformationen, sodass Sie sich für jeden Anbieter nur einmal anmelden können. Wenn Sie eine andere Google App herunterladen oder mehrmals auf eine App zugreifen, geben Sie die Anmeldeinformationen nur einmal ein

0
Pomagranite