Tilføjelse af et mål for sikkerhed til Android's delte præferencer

Hvis du har frigivet en applikation på Googles Android-marked, og den applikation krævede din brugertype i enhver form for legitimationsoplysninger, er chancerne for, at din ansøgning var tilgængelig i alt cirka tolv minutter, før du modtog din første brugeranmodning om at tillade, at disse legitimationsoplysninger var gemt på telefonen. Brugere hader at skrive en adgangskode, hver gang de vil bruge din applikation. Sikkerhedsrisiko eller ej, på et tidspunkt skal du muligvis lade nogle brugere gemme følsomme præferencer, eller chancerne er for at de bare ikke bruger din applikation.

På Apples iOS-platform opbevares applikationspræferencer i noget, der kaldes nøglekæden. Dataelementer, der er gemt i nøglekæden, krypteres automatisk af operativsystemet. Android's foretrukne mekanisme til at holde styr på brugerpræferencer, klassen SharedPreferences, er imidlertid ikke så sikker. Mens klassen SharedPreferences faktisk er ligetil og let for en udvikler at bruge, bliver det på en rodet enhed åbenlyst, at den simpelthen gemmer dataene i en XML-fil.

Hvad dette betyder er, at det falder på vores skuldre som ansvarlige Android-appudviklere til at beslutte, hvilke indstillinger vi tillader brugeren at gemme i den delte præferencesfil og, når det er relevant, implementere vores egne krypterings- / dekrypteringsalgoritmer. Formålet med denne artikel er ikke at få dig op med hastigheden med datakryptering. Det er et bredt emne, og der er masser af bøger tilgængelige om chifferteori.

I stedet vil jeg gerne dele med dig en udvidet version af standard EditText-widgeten, som giver dig udvikleren mulighed for at anvende uanset hvilket krypteringsniveau, du mener er passende til din applikation. Den udvidede widget har vist sig at være en praktisk måde for mig at anvende et mål for sikkerhed på alle brugerpræferencer, jeg vælger, uden at kræve, at jeg konstant beskæftiger sig med kodning / dekodning af strengene. Desuden, hvis jeg på et tidspunkt i fremtiden beslutter, at der er behov for oksekødere sikkerhedsciffer, skal jeg kun ændre krypteringsmekanismen i widgetten i stedet for at refaktorere hele applikationen.

Lad os tage et kig, skal vi?

  1. Opret et nyt Android-projekt (målretning efter hvilken SDK du foretrækker).
  2. I vores / src-fil skal vi tilføje en ny klasse, der udvider android.widget.EditText.
 MyEditText.Java public class MyEditText udvider EditText { 
 offentlig MyEditText (Kontekstkontekst, AttributeSet attrs) { 
 super (kontekst, attrs); 
 } 
 } 

Gotcha! For at henvise til en udvidet widget fra din XML-layoutfil, skal du tilsidesætte denne bestemte konstruktørsignatur. Selvom du også kan tilsidesætte de to andre signaturer, vil manglende tilsidesættelse af kontekst / attribut-underskrift resultere i en styrke, der lukkes, hver gang du indlæser en xml-layoutressource, der refererer til MyEditText.

3. Udover at tilsidesætte konstruktøren, ønsker vi at implementere en brugerdefineret version af standard widget-get / set-tekstfunktioner. Disse kloner signaturen til standard-get / set-metoder, men tager en yderligere parameter, et flag, der angiver, om kryptering eller dekryptering er passende.

 public void setText (CharSequence-tekst, boolsk doDecrypt) 
 { 
 if (doDecrypt) { 
 tekst = rot13Dekode (tekst); 
 } 
 super .setText (tekst); 
 } 
 public Editable getText ( boolean doEncrypt) 
 { 
 Redigerbar e = super .getText (); 
 if (doEncrypt) { 
 e = rot13Kode (e); 
 } 
 return e; 
 } 

Hvis du vil lægge mærke til, når flaget er indstillet, kalder jeg en rot13-kode / -kodningskode. Dette er bare noget simpelt, jeg piskede op til denne demo. Du skal afgøre, hvilket sikkerhedsniveau der er passende til din ansøgning. Hvis du er usikker, foreslår jeg, at du bruger BouncyCastle-bibliotekerne, der er tilgængelige som en del af standard Android-builden, da disse giver et antal passende ciffer

 public Editable rot13Encode (CharSequence input) { 
 StringBuilder output = ny StringBuilder (); 
 for ( int i = 0; i <input.length (); i ++) { 
 char c = input.charAt (i); 
 hvis ((c 126)) { 
 // uden for vores udskrivbare sortiment, så lad være i takt 
 output.append (c); 
 } andet { 
 //flytte 
 c + = 13; 
 hvis (c> 126) { 
 // wrap 
 c - = ((126 - 32) + 1); 
 } 
 output.append (c); 
 } 
 } 
 returnere ny SpannableStringBuilder (output); 
 } 
 public CharSequence rot13Decode (CharSequence input) { 
 StringBuilder output = ny StringBuilder (); 
 for ( int i = 0; i <input.length (); i ++) { 
 char c = input.charAt (i); 
 hvis ((c 126)) { 
 // uden for vores udskrivbare sortiment, så lad være i takt 
 output.append (c); 
 } andet { 
 //flytte 
 c- = 13; 
 hvis (c <32) { 
 // wrap 
 c + = ((126 - 32) + 1); 
 } 
 output.append (c); 
 } 
 } 
 return output.toString (); 
 } 

Gotcha! Bemærk, at kodefunktionen returnerer en type redigerbar? Dette er en grænseflade, ikke en faktisk variabel type. Googles dokumentation gør et ret godt stykke arbejde med at forklare, hvordan man konverterer en redigerbar til en streng, men det tager virkelig noget at grave for at finde ud af, hvordan man går fra en streng til en redigerbar. Oprettelse af en ny SpannableStringBuilder-instans fra en eksisterende CharSequence ser ud til at gøre suset ganske handy.

4. Nu hvor vi kan tilføje vores udvidede widget til vores XML-fil, lad os oprette layoutet til vores demo i mappen / res / layout.

 main.xml 
 "1.0" encoding = "utf-8" ?> 
 "Http://schemas.android.com/apk/res/android" 
 android: orientering = "lodret" 
 android: layout_width = "fill_parent" 
 android: layout_height = "fill_parent" 
 android: polstring = "4dip" > 
 android: layout_width = "fill_parent" 
 android: layout_height = "wrap_content" 

android: layout_marginBottom = "20dip"

android: tyngdekraft = "center"

android: text = "@ streng / hej" />

 android: layout_width = "wrap_content" 
 android: layout_height = "wrap_content" 
 android: layout_gravity = "center" 
 android: text = "@ streng / prompt" /> 
 android: layout_width = "fill_parent" 
 android: layout_height = "wrap_content" 
 android: layout_marginBottom = "20dip" 
 android: id = "@ + id / entry_field" /> 
 android: layout_width = "fill_parent" 
 android: layout_height = "wrap_content" 
 android: id = "@ + id / gem" 
 android: text = "@ string / save_pref" /> 
 android: layout_width = "fill_parent" 
 android: layout_height = "wrap_content" 
 android: id = "@ + id / hent" 
 android: layout_marginBottom = "20dip" 
 android: text = "@ streng / hent_pref" /> 
 android: id = "@ + id / showme" 
 android: layout_width = "wrap_content" 
 android: layout_height = "wrap_content" 
 android: markeret = "sandt" 
 android: layout_gravity = "center" 
 android: text = "@ string / show_text" /> 

5. Vi tilføjer et par standardindstillinger til vores mappe res / Values.

 strings.xml  "1.0" encoding = "utf-8" ?> 
 "hej"> Skjul adgangskordsdemo 
 "app_name"> HideMe 
 "save_pref"> Gem præference 
 "retrieve_pref"> Hent præference 
 "prompt"> Skriv nogle tekst nedenfor: 
 "show_text"> Vis adgangskode, mens du skriver 

6. Nu er vi klar til vores hovedaktivitet.

 Main.Java public class Main 
 udvider aktiviteten 
 implementerer OnCheckedChangeListener, OnClickListener 
 { 
 // vigtigste 
 } 

7. I onCreate-metoden har vi bare brug for at koble vores UI-elementer.

 @Override 
 offentligt tomrum onCreate (Bundle gemtInstanceState) { 
 super .onCreate (gemtInstanceState); 
 setContentView (R.layout. main ); 
 CheckBox cb = (CheckBox) findViewById (R.id. Showme ); // Vis, mens du skriver 
 cb.setOnCheckedChangeListener ( dette ); 
 Button sb = (Button) findViewById (R.id. Save ); // gem til præferencer 
 sb.setOnClickListener ( dette ); 
 Knap rb = (knap) findViewById (R.id. Hente); // få fra præferencer 
 rb.setOnClickListener ( dette ); 
 } 

8. Med henblik på demoen har jeg tilføjet et afkrydsningsfelt, der giver dig mulighed for at vise eller ikke vise, hvad der indtastes i vores redigeringsfelt. Dette er en smuk nifty funktion indbygget i Android rediger tekst tekst widget kaldet en transformation.

 @Override 
 public void onCheckedChanged (CompoundButton buttonView, boolean isChecked) { 
 MyEditText et = (MyEditText) findViewById (R.id. Entry_field ); 
 hvis (isChecked) { 
 et.setTransformationMethod ( null ); 
 } andet { 
 et.setTransformationMethod ( nyt PasswordTransformationMethod ()); 
 } 
 } 

9. Og sidst men ikke mindst har vi vores knapklik. Ved blot at videregive vores flag, når vi får og indstiller teksten i MyEditText, kan vi få almindelig eller krypteret tekst. Toastmeddelelsen giver en visuel indikator for, hvad der faktisk gemmes i og hentes fra præferencesfilen på enheden.

 @Override 
 offentligt ugyldigt onClick (Vis v) { 
 MyEditText et = (MyEditText) findViewById (R.id. Entry_field ); 
 SharedPreferences-indstillinger = getSharedPreferences ("MyPreferences", 0); 
 if (v.getId () == R.id. gemme ) { 
 String encodedPassword = et.getText ( true ) .toString (); 
 SharedPreferences.Editor editor = settings.edit (); 
 editor.putString ("adgangskode", kodet passord); 
 editor.commit (); 
 Ristet brød. makeText (Main. this, kodedPassword, Toast. LENGTH_LONG ) .show (); 
 } andet { 
 String encodedPassword = settings.getString ("password", ""); 
 et.setText (kodet passord, sandt ); 
 Ristet brød. makeText (Main. this, kodedPassword, Toast. LENGTH_LONG ) .show (); 
 } 
 } 

Og der har du det - en praktisk, fleksibel mekanisme til at tilføje en vis nødvendig sikkerhed til dine egne præferencer filer. Hvis du gerne vil downloade hele projektet, er kilden tilgængelig her. God fornøjelse!

© Copyright 2021 | pepebotifarra.com