web-dev-qa-db-fra.com

Android Login - Authentificateur de compte vs authentification manuelle

Je suis sur le point d'implémenter la connexion avec l'authentification des utilisateurs dans mon application.

Ma première idée a été de le faire manuellement, d'enregistrer le nom d'utilisateur et le mot de passe sur le serveur, d'obtenir un jeton d'authentification, de l'enregistrer et de l'utiliser dans les demandes suivantes.

Après avoir parcouru Google, j'ai compris que la bonne façon de le faire sur Android utilisait l'authentificateur de compte. J'ai vu quelques exemples de son implémentation mais je ne comprends pas l'avantage de le faire de cette façon? Est-ce parce que je peux avoir plus d'un compte stocké? Est-ce à cause de problèmes de synchronisation? J'apprécierais que quelqu'un puisse m'expliquer cela. Cela me ferait probablement mieux comprendre le code et pourquoi il fait quoi c'est.

35
Daniel Julio

Puis-je avoir plus d'un compte enregistré?

Oui. Voyez comment Google ou Facebook le font.

Est-ce à cause de problèmes de synchronisation?

Oui, vous avez besoin d'un compte pour utiliser le mécanisme de synchronisation comme SyncAdapter

Pourquoi devriez-vous utiliser AccountAuthenticator?

  • Prise en charge du mécanisme de synchronisation en arrière-plan comme SyncAdapter;

  • Manière standard d'authentifier les utilisateurs;

  • Prend en charge différents jetons;

  • Partage de compte avec différents privilèges

Que devez-vous faire?

1). Créer Authenticator;

2). Créez Activity pour la connexion utilisateur;

3). Créez Service pour communiquer avec le compte.

Termes.

AccountManager - il gère le compte sur l'appareil. Demandez des jetons d'authentification que vous devez utiliser AccountManager.

AbstractAccountAuthenticator - composant pour travailler avec les types de comptes. Il contient toute la logique de travail avec le compte (autorisation, droits d'accès, etc.) Un AbstractAccountAuthenticator peut être utilisé par différentes applications (comme le compte Google pour Gmail, Calendar, Drive, etc.)

AccountAuthenticatorActivity - base Activity, pour autoriser/créer un compte. AccountManager appelle ce compte s'il est nécessaire d'identifier le compte (le jeton n'existe pas ou a expiré)

Comment tout cela fonctionne-t-il? Regardez l'image ci-dessous:

Android account management diagram

Pas.

1). Créer Authenticator;

Vous devez étendre AbstractAccountAuthenticator et remplacer 7 méthodes:

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

Exemple:

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;
    }
}

Explication:

Donc, vous devez voir seulement 2 méthodes: addAccount, getAuthToken.

Dans addAccount, j'ai ajouté quelques paramètres de configuration, qui seront utilisés par mon Activity pour la connexion utilisateur. Le point principal ici est intent.putExtra(Config.ARG_ACCOUNT_TYPE, accountType); - vous devez spécifier le type de compte ici. D'autres manipulations ne sont pas nécessaires.

Dans getAuthToken - Lisez les commentaires s'il vous plaît . J'ai copié-collé cette méthode depuis dinicAuthenticator.Java

De plus, vous aurez besoin des autorisations suivantes dans votre AndroidManifest.xml:

<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" />

Résumé des méthodes addAccount et getAuthToken

Essayez d'obtenir le jeton, si le jeton existe, retournez le résultat, sinon vous verrez Activity pour l'autorisation

2). Créez Activity pour la connexion utilisateur;

Voir AuthenticatorActivity

Brève explication: Créez un formulaire avec UserId et Password. À l'aide des données UserId & Password, obtenez le jeton d'authentification du serveur, puis exécutez l'étape suivante:

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

3). Créez un Service pour communiquer avec le compte.

Voir dinicAuthenticatorService

N'oubliez pas d'ajouter cette ligne dans AndroidManifest.xml À Service:

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

Et aussi dans res/xml Ajoutez le fichier authenticator.xml:

<?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"/>

C'est tout. Vous pouvez utiliser votre AccountAuthenticator.

Pour les matériaux sources grâce à

101
Alexander

Le AccountManager est bon pour les raisons suivantes:

  • La première consiste à stocker plusieurs noms de compte avec différents niveaux d'accès aux fonctionnalités de l'application sous un seul type de compte. Par exemple, dans une application de streaming vidéo, l'un peut avoir deux noms de compte: l'un avec un accès démo à un nombre limité de vidéos et l'autre avec un accès d'un mois à toutes les vidéos. Cependant, ce n'est pas la principale raison d'utiliser Accounts, car vous pouvez facilement gérer cela dans votre application sans avoir besoin de cette chose Accounts sophistiquée….
  • L'autre avantage de l'utilisation de Accounts est de se débarrasser de l'autorisation traditionnelle avec nom d'utilisateur et mot de passe chaque fois qu'une fonctionnalité autorisée est demandée par l'utilisateur, car l'authentification a lieu en arrière-plan et l'utilisateur est invité à saisir son mot de passe seulement dans certaines conditions, que j'y reviendrai plus tard.
  • L'utilisation de la fonction Accounts dans Android supprime également la nécessité de définir son propre type de compte. Vous avez probablement rencontré des applications utilisant des comptes Google pour l'autorisation, ce qui vous évite d'avoir à créer un nouveau compte et en se souvenant de ses informations d'identification pour l'utilisateur.
  • Accounts peut être ajouté indépendamment via Paramètres → Comptes
  • L'autorisation d'utilisateur multiplateforme peut être facilement gérée à l'aide de Accounts. Par exemple, le client peut accéder au matériel protégé en même temps dans son Android et PC sans avoir besoin de connexions récurrentes.
  • Du point de vue de la sécurité, l'utilisation du même mot de passe dans chaque demande au serveur permet une écoute indiscrète dans les connexions non sécurisées. Le cryptage du mot de passe n'est pas suffisant ici pour empêcher le vol de mot de passe.
  • Enfin, une raison importante pour l'utilisation de la fonction Accounts dans Android est de séparer les deux parties impliquées dans toute entreprise dépendante de Accounts, appelée authentificateur et ressource propriétaire, sans compromettre les informations d'identification du client (utilisateur) Les termes peuvent sembler plutôt vagues, mais n'abandonnez pas avant d'avoir lu le paragraphe suivant… ????

Permettez-moi de développer ce dernier avec un exemple d'application de streaming vidéo. La société A est titulaire d'une entreprise de streaming vidéo sous contrat avec la société B pour fournir à certains de ses membres des services de streaming premium. La société B utilise une méthode de nom d'utilisateur et de mot de passe pour reconnaître son utilisateur. Pour que la société A reconnaisse les membres premium de B, une façon serait d'obtenir la liste de ceux-ci auprès de B et d'utiliser un mécanisme de correspondance de nom d'utilisateur/mot de passe similaire. De cette façon, l'authentificateur et le propriétaire de la ressource sont les mêmes (société A). Outre l'obligation des utilisateurs de mémoriser un deuxième mot de passe, il est très probable qu'ils définissent le même mot de passe que le profil de leur entreprise B pour utiliser les services de A. Ce n'est évidemment pas favorable.

Pour remédier aux lacunes ci-dessus, OAuth a été introduit. En tant que norme ouverte d'autorisation, dans l'exemple ci-dessus, OAuth exige que l'autorisation soit effectuée par la société B). (authentificateur) en émettant un jeton appelé jeton d'accès pour les utilisateurs éligibles (tiers), puis en fournissant le jeton à la société A (propriétaire de la ressource). Ainsi, aucun jeton ne signifie aucune éligibilité.

J'ai développé plus à ce sujet et plus sur AccountManager sur mon site Web à ici

7
Ali Nem

Dans les paramètres d'Android, vous avez des comptes pour votre type de compte et à partir de là, vous pouvez ajouter un compte. AccountManager est également un emplacement central pour stocker les informations d'identification afin que vous ne vous connectiez qu'une seule fois pour chaque fournisseur. Si vous téléchargez une autre application Google ou accédez à une application plusieurs fois, vous ne saisissez les informations d'identification qu'une seule fois

0
Pomagranite