What is the most appropriate way to store user settings in Android application

后端 未结 14 2056
隐瞒了意图╮
隐瞒了意图╮ 2020-11-22 05:38

I am creating an application which connects to the server using username/password and I would like to enable the option \"Save password\" so the user wouldn\'t have to type

相关标签:
14条回答
  • 2020-11-22 06:20

    I'll throw my hat into the ring just to talk about securing passwords in general on Android. On Android, the device binary should be considered compromised - this is the same for any end application which is in direct user control. Conceptually, a hacker could use the necessary access to the binary to decompile it and root out your encrypted passwords and etc.

    As such there's two suggestions I'd like to throw out there if security is a major concern for you:

    1) Don't store the actual password. Store a granted access token and use the access token and the signature of the phone to authenticate the session server-side. The benefit to this is that you can make the token have a limited duration, you're not compromising the original password and you have a good signature that you can use to correlate to traffic later (to for instance check for intrusion attempts and invalidate the token rendering it useless).

    2) Utilize 2 factor authentication. This may be more annoying and intrusive but for some compliance situations unavoidable.

    0 讨论(0)
  • 2020-11-22 06:21

    You can also check out this little lib, containing the functionality you mention.

    https://github.com/kovmarci86/android-secure-preferences

    It is similar to some of the other aproaches here. Hope helps :)

    0 讨论(0)
  • 2020-11-22 06:24

    In general SharedPreferences are your best bet for storing preferences, so in general I'd recommend that approach for saving application and user settings.

    The only area of concern here is what you're saving. Passwords are always a tricky thing to store, and I'd be particularly wary of storing them as clear text. The Android architecture is such that your application's SharedPreferences are sandboxed to prevent other applications from being able to access the values so there's some security there, but physical access to a phone could potentially allow access to the values.

    If possible I'd consider modifying the server to use a negotiated token for providing access, something like OAuth. Alternatively you may need to construct some sort of cryptographic store, though that's non-trivial. At the very least, make sure you're encrypting the password before writing it to disk.

    0 讨论(0)
  • 2020-11-22 06:24

    This is a supplemental answer for those arriving here based on the question title (like I did) and don't need to deal with the security issues related to saving passwords.

    How to use Shared Preferences

    User settings are generally saved locally in Android using SharedPreferences with a key-value pair. You use the String key to save or look up the associated value.

    Write to Shared Preferences

    String key = "myInt";
    int valueToSave = 10;
    
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putInt(key, valueToSave).commit();
    

    Use apply() instead of commit() to save in the background rather than immediately.

    Read from Shared Preferences

    String key = "myInt";
    int defaultValue = 0;
    
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
    int savedValue = sharedPref.getInt(key, defaultValue);
    

    The default value is used if the key isn't found.

    Notes

    • Rather than using a local key String in multiple places like I did above, it would be better to use a constant in a single location. You could use something like this at the top of your settings activity:

        final static String PREF_MY_INT_KEY = "myInt";
      
    • I used an int in my example, but you can also use putString(), putBoolean(), getString(), getBoolean(), etc.

    • See the documentation for more details.

    • There are multiple ways to get SharedPreferences. See this answer for what to look out for.

    0 讨论(0)
  • 2020-11-22 06:24

    you need to use the sqlite, security apit to store the passwords. here is best example, which stores passwords, -- passwordsafe. here is link for the source and explanation -- http://code.google.com/p/android-passwordsafe/

    0 讨论(0)
  • 2020-11-22 06:25

    This answer is based on a suggested approach by Mark. A custom version of the EditTextPreference class is created which converts back and forth between the plain text seen in the view and an encrypted version of the password stored in the preferences storage.

    As has been pointed out by most who have answered on this thread, this is not a very secure technique, although the degree of security depends partly on the encryption/decryption code used. But it's fairly simple and convenient, and will thwart most casual snooping.

    Here is the code for the custom EditTextPreference class:

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

    This shows how it can be used - this is the "items" file that drives the preferences display. Note it contains three ordinary EditTextPreference views and one of the custom EditPasswordPreference views.

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

    As for the actual encryption/decryption, that is left as an exercise for the reader. I'm currently using some code based on this article http://zenu.wordpress.com/2011/09/21/aes-128bit-cross-platform-java-and-c-encryption-compatibility/, although with different values for the key and the initialization vector.

    0 讨论(0)
提交回复
热议问题