45 votes

Meilleure option pour stocker le nom d'utilisateur et le mot de passe dans une application Android

Je développe une application Android où l'utilisateur doit s'identifier pour effectuer des opérations. Mais la plupart du temps, sur un téléphone Android, les gens utilisent "Gardez-moi connecté" Dans ce cas, je devrai maintenir la valeur de Nom d'utilisateur : y Mot de passe dans mon application. Dois-je utiliser SharedPreferences ou une base de données SQLite ou quelque chose d'autre que je peux utiliser.
Et comment puis-je le sécuriser ?

36voto

Mike Points 3295

Oui, c'est délicat sur Android. Vous ne voulez pas stocker le mot de passe en clair dans les préférences, car toute personne possédant un appareil enraciné affichera son mot de passe au monde entier. D'un autre côté, vous ne pouvez pas utiliser un mot de passe crypté, car vous devriez stocker votre clé de cryptage/décryptage quelque part sur l'appareil, ce qui est également susceptible d'être attaqué par un root.

Une solution que j'ai utilisée il y a quelque temps consiste à demander au serveur de générer un "ticket" qu'il renvoie à l'appareil et qui est valable pendant un certain temps. Ce ticket est utilisé par l'appareil pour toutes les communications, en utilisant SSL bien sûr pour que les gens ne puissent pas voler votre ticket. De cette façon, l'utilisateur authentifie son mot de passe sur le serveur une fois, le serveur renvoie un ticket qui expire, et le mot de passe n'est jamais stocké sur l'appareil.

Plusieurs mécanismes d'authentification à trois pattes, comme OpenID, Facebook, voire les API de Google, utilisent ce mécanisme. L'inconvénient est que de temps en temps, lorsque le ticket expire, l'utilisateur doit se reconnecter.

En fin de compte, cela dépend du degré de sécurité que vous souhaitez donner à votre application. S'il s'agit simplement de distinguer les utilisateurs, et qu'aucune information super secrète n'est stockée, comme des comptes bancaires ou des groupes sanguins, alors peut-être que sauvegarder le PWD en clair sur le périphérique est tout à fait acceptable :)

Bonne chance, quelle que soit la méthode que vous choisissez pour votre situation particulière !

Edit : Je dois noter que cette technique transfère la responsabilité de la sécurité au serveur - vous voudrez utiliser des hachages salés pour la comparaison des mots de passe sur le serveur, une idée que vous verrez dans certains des autres commentaires pour cette question. Cela permet d'éviter que le mot de passe en clair n'apparaisse ailleurs que dans la vue EditText de l'appareil, dans la communication SSL avec le serveur et dans la RAM du serveur pendant qu'il s'occupe de saler et de hacher le mot de passe. Il n'est jamais stocké sur le disque, ce qui est une bonne chose™.

27voto

knaak Points 393

Comme d'autres l'ont dit, il n'existe pas de moyen sûr de stocker un mot de passe dans Android qui protège entièrement les données. Le hachage/cryptage du mot de passe est une excellente idée, mais il ne fera que ralentir le "craqueur".

Ceci étant dit, voici ce que j'ai fait :

1) J'ai utilisé ceci simplecryto.java classe qui prend une graine et un texte et le crypte. 2) J'ai utilisé SharedPreferences en mode privé qui protège le fichier sauvegardé sur les appareils non enracinés. 3) La graine que j'ai utilisée pour simplecryto est un tableau d'octets qui est un peu plus difficile à trouver par les décompilateurs qu'une chaîne.

Mon application a récemment été examinée par un groupe de sécurité "white hat" engagé par mon entreprise. Il a signalé ce problème et indiqué que je devrais utiliser OAUTH, mais il l'a également classé dans la catégorie des problèmes à faible risque, ce qui signifie qu'il n'est pas génial, mais pas assez grave pour empêcher la publication.

N'oubliez pas que le "craqueur" doit avoir un accès physique à l'appareil ET le racler ET être suffisamment attentif pour trouver la graine.

Si vous vous souciez vraiment de la sécurité, ne proposez pas d'option "me garder connecté".

7voto

Marvin Pinto Points 8292

Au minimum, stockez-le dans SharedPreferences (mode privé) et n'oubliez pas de dièse le mot de passe. Bien que cela ne fasse pas vraiment de différence avec un utilisateur malveillant (ou un appareil enraciné), c'est quelque chose.

3voto

Climax Points 63

Vous pourriez utiliser Préférences partagées cryptées de la bibliothèque de sécurité Jetpack. Il fonctionne très bien pour les paramètres de type clé-valeur.

Il enveloppe SharedPreferences qui assure un cryptage/décryptage sécurisé tout en conservant la même API que celle de l'API de l'UE. SharedPreferences .

Comme dans leur exemple :

  String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);

  SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
      "secret_shared_prefs",
      masterKeyAlias,
      context,
      EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
      EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
  );

  // use the shared preferences and editor as you normally would
  SharedPreferences.Editor editor = sharedPreferences.edit();

3voto

Je voulais sauvegarder le mot de passe dans les préférences partagées, donc je l'ai implémenté en privé d'abord comme le code ci-dessous

public class PrefManager {

  private SharedPreferences pref;
  private SharedPreferences.Editor editor;

  public PrefManager(Context context) {
    pref = context.getSharedPreferences("PROJECT_NAME", Context.MODE_PRIVATE);
    editor = pref.edit();
  }

}

et pour sauvegarder le mot de passe, j'ai utilisé un algorithme pour encrypter et décrypter

algorithme de cryptage

 public void setPassword(String password) {
      int len = password.length();
      len /= 2;
      StringBuilder b1 = new StringBuilder(password.substring(0, len));
      StringBuilder b2 = new StringBuilder(password.substring(len));
      b1.reverse();
      b2.reverse();
      password = b1.toString() + b2.toString();

    editor.putString("password", password);
    editor.apply();
  }

algorithme de décryptage

  public String getPassword() {
    String password = pref.getString("password", null);
    int len = password.length();
    len /= 2;
    StringBuilder b1 = new StringBuilder(password.substring(0, len));
    StringBuilder b2 = new StringBuilder(password.substring(len));
    password = b1.reverse().toString() + b2.reverse().toString();
    return password;
  }

NOTE :

Dans cet algorithme simple, j'ai divisé le mot de passe du milieu en deux morceaux, je l'ai retourné et je l'ai remis ensemble. C'était juste une idée et vous pouvez utiliser vos propres algorithmes pour modifier le mode d'enregistrement du mot de passe.

CODE COMPLET

import android.content.Context;
import android.content.SharedPreferences;

public class PrefManager {

  private SharedPreferences pref;
  private SharedPreferences.Editor editor;

  public PrefManager(Context context) {
    pref = context.getSharedPreferences("PROJECT_NAME", Context.MODE_PRIVATE);
    editor = pref.edit();
  }
  public String getPassword() {
    String password = pref.getString("password", null);
    int len = password.length();
    len /= 2;
    StringBuilder b1 = new StringBuilder(password.substring(0, len));
    StringBuilder b2 = new StringBuilder(password.substring(len));
    password = b1.reverse().toString() + b2.reverse().toString();
    return password;
  }

  public void setPassword(String password) {
      int len = password.length();
      len /= 2;
      StringBuilder b1 = new StringBuilder(password.substring(0, len));
      StringBuilder b2 = new StringBuilder(password.substring(len));
      b1.reverse();
      b2.reverse();
      password = b1.toString() + b2.toString();

    editor.putString("password", password);
    editor.apply();
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X