Каков наиболее подходящий способ хранения пользовательских настроек в приложении Android - PullRequest
296 голосов
/ 24 апреля 2009

Я создаю приложение, которое подключается к серверу, используя имя пользователя / пароль, и я хочу включить опцию «Сохранить пароль», чтобы пользователю не приходилось вводить пароль при каждом запуске приложения.

Я пытался сделать это с помощью общих настроек, но не уверен, что это лучшее решение.

Буду признателен за любые предложения о том, как хранить пользовательские значения / настройки в приложении Android.

Ответы [ 14 ]

1 голос
/ 06 сентября 2013

Этот ответ основан на предлагаемом подходе Марка. Создается пользовательская версия класса EditTextPreference, которая преобразует назад и вперед между простым текстом, видимым в представлении, и зашифрованной версией пароля, хранящейся в хранилище настроек.

Как указывалось большинством, кто ответил в этой теме, это не очень безопасный метод, хотя степень безопасности частично зависит от используемого кода шифрования / дешифрования. Но это довольно просто и удобно, и помешает большинству случайных слежки.

Вот код для пользовательского класса EditTextPreference:

package com.Merlinia.OutBack_Client;

import android.content.Context;
import android.preference.EditTextPreference;
import android.util.AttributeSet;
import android.util.Base64;

import com.Merlinia.MEncryption_Main.MEncryptionUserPassword;


/**
 * This class extends the EditTextPreference view, providing encryption and decryption services for
 * OutBack user passwords. The passwords in the preferences store are first encrypted using the
 * MEncryption classes and then converted to string using Base64 since the preferences store can not
 * store byte arrays.
 *
 * This is largely copied from this article, except for the encryption/decryption parts:
 * https://groups.google.com/forum/#!topic/android-developers/pMYNEVXMa6M
 */
public class EditPasswordPreference  extends EditTextPreference {

    // Constructor - needed despite what compiler says, otherwise app crashes
    public EditPasswordPreference(Context context) {
        super(context);
    }


    // Constructor - needed despite what compiler says, otherwise app crashes
    public EditPasswordPreference(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
    }


    // Constructor - needed despite what compiler says, otherwise app crashes
    public EditPasswordPreference(Context context, AttributeSet attributeSet, int defaultStyle) {
        super(context, attributeSet, defaultStyle);
    }


    /**
     * Override the method that gets a preference from the preferences storage, for display by the
     * EditText view. This gets the base64 password, converts it to a byte array, and then decrypts
     * it so it can be displayed in plain text.
     * @return  OutBack user password in plain text
     */
    @Override
    public String getText() {
        String decryptedPassword;

        try {
            decryptedPassword = MEncryptionUserPassword.aesDecrypt(
                     Base64.decode(getSharedPreferences().getString(getKey(), ""), Base64.DEFAULT));
        } catch (Exception e) {
            e.printStackTrace();
            decryptedPassword = "";
        }

        return decryptedPassword;
    }


    /**
     * Override the method that gets a text string from the EditText view and stores the value in
     * the preferences storage. This encrypts the password into a byte array and then encodes that
     * in base64 format.
     * @param passwordText  OutBack user password in plain text
     */
    @Override
    public void setText(String passwordText) {
        byte[] encryptedPassword;

        try {
            encryptedPassword = MEncryptionUserPassword.aesEncrypt(passwordText);
        } catch (Exception e) {
            e.printStackTrace();
            encryptedPassword = new byte[0];
        }

        getSharedPreferences().edit().putString(getKey(),
                                          Base64.encodeToString(encryptedPassword, Base64.DEFAULT))
                .commit();
    }


    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        if (restoreValue)
            getEditText().setText(getText());
        else
            super.onSetInitialValue(restoreValue, defaultValue);
    }
}

Это показывает, как его можно использовать - это файл "items", который управляет отображением настроек. Обратите внимание, что он содержит три обычных представления EditTextPreference и одно из пользовательских представлений EditPasswordPreference.

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <EditTextPreference
        android:key="@string/useraccountname_key"
        android:title="@string/useraccountname_title"
        android:summary="@string/useraccountname_summary"
        android:defaultValue="@string/useraccountname_default"
        />

    <com.Merlinia.OutBack_Client.EditPasswordPreference
        android:key="@string/useraccountpassword_key"
        android:title="@string/useraccountpassword_title"
        android:summary="@string/useraccountpassword_summary"
        android:defaultValue="@string/useraccountpassword_default"
        />

    <EditTextPreference
        android:key="@string/outbackserverip_key"
        android:title="@string/outbackserverip_title"
        android:summary="@string/outbackserverip_summary"
        android:defaultValue="@string/outbackserverip_default"
        />

    <EditTextPreference
        android:key="@string/outbackserverport_key"
        android:title="@string/outbackserverport_title"
        android:summary="@string/outbackserverport_summary"
        android:defaultValue="@string/outbackserverport_default"
        />

</PreferenceScreen>

Что касается фактического шифрования / дешифрования, то это оставлено в качестве упражнения для читателя. В настоящее время я использую код, основанный на этой статье http://zenu.wordpress.com/2011/09/21/aes-128bit-cross-platform-java-and-c-encryption-compatibility/,, но с разными значениями ключа и вектора инициализации.

0 голосов
/ 07 ноября 2018

Я использую Android KeyStore для шифрования пароля с использованием RSA в режиме ECB, а затем сохраняю его в SharedPreferences.

Когда я хочу вернуть пароль, я читаю зашифрованный из SharedPreferences и расшифровываю его с помощью хранилища ключей.

С помощью этого метода вы генерируете открытую / закрытую пару ключей, где частная надежно хранится и управляется Android.

Вот ссылка о том, как это сделать: Учебник по Android KeyStore

0 голосов
/ 18 октября 2013

общие настройки - это самый простой способ хранения данных нашего приложения. но возможно, что любой может очистить наши общие данные о предпочтениях через менеджер приложений. поэтому я не думаю, что это полностью безопасно для нашего приложения

0 голосов
/ 27 апреля 2009

вам нужно использовать sqlite, security apit для хранения паролей. Вот лучший пример, который хранит пароли, - Passwordsafe. вот ссылка на источник и объяснение - http://code.google.com/p/android-passwordsafe/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...