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.
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.
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:
1). Créer Authenticator
;
Vous devez étendre AbstractAccountAuthenticator
et remplacer 7 méthodes:
Bundle editProperties(AccountAuthenticatorResponse response, String accountType)
lienBundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options)
lienBundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options)
lienBundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)
lienString getAuthTokenLabel(String authTokenType)
lienBundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)
lienBundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features)
lienExemple:
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" />
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;
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
.
di Cohen ;
Daniel Serdyukov (tout le texte traduit de son article (sauf mes petits ajouts) "Synchronisation dans les applications Android. Partie 1" en russe uniquement. lien: http://habrahabr.ru/company/e-Legion/blog/206210/ )
Le AccountManager
est bon pour les raisons suivantes:
Accounts
, car vous pouvez facilement gérer cela dans votre application sans avoir besoin de cette chose Accounts
sophistiquée….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.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 → ComptesAccounts
. 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.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
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