2017-02-20 4 views
0

В моем приложении я использую пароль пользователей в качестве ключа шифрования для средств шифрования. Я шифрую носитель, используя PBEWithMD5AndDES, и это отлично работает с паролем, хранящимся в общих предпочтениях. Теперь для достижения уровня безопасности я удаляю пароль из общих настроек и использую синглтон, который поддерживается только во время сеанса приложения (так как приложение выходит из системы автоматически, требуя ввода пароля). Ниже мой синглтон:Singleton Instance возвращает null

public class Credentials { 

private static Credentials dataObject = null; 

private Credentials() { 
// left blank intentionally 
} 

public static Credentials getInstance() { 
if (dataObject == null) 
    dataObject = new Credentials(); 
return dataObject; 
} 

private char[] user_password; 

public char[] getUser_password() { 

return user_password; 
} 

public void setUser_password(char[] user_password) { 

this.user_password = user_password; 
} 
} 

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

char[] pswd = Credentials.getInstance().getUser_password(); 

Что может быть причиной этого? есть ли какой-либо другой метод, который я могу использовать, кроме одноэлементного?

+1

'Credentials.getInstance()' не может возвращать 'null'. Это то, что вы никогда не вызывали 'setUser_password' на этом экземпляре, поэтому' Credentials.getInstance(). GetUser_password() 'делает. И если вы считаете, что вы вызвали 'setUser_password' (с ненулевым параметром), проблема в том, что ваш singleton-класс не является потокобезопасным. –

+0

@James Wahome: Ваш 'пароль' - это null не singleton !! – AndiGeeky

+0

Добавить правильную проверку для нулевого объекта для singleton. Экземпляр и значения возвращаются по его функциям. –

ответ

-1

В качестве альтернативы вы можете сохранить пароль с помощью встроенного Sqlite db, хотя я бы порекомендовал вам сохранить его зашифрованным для максимальной защиты. Вы можете сделать это в 4 этапа:

2) Создайте объект сущности для хранения пароля:

public class Password { 
    int password_id; // will be auto-increamted 
    String password; 

    public Password(int password_id, String password) { 
     this.password_id = password_id; 
     this.password = password; 
    } 
// getter/setters ... 
} 

2) Создание SQLITE утилиты объекта:

public class SQLiteDBAdapter { 

    protected static final String DATABASE_NAME = "mydb"; 
    protected static final int DATABASE_VERSION = 1; 

    protected Context context; 
    protected static DatabaseHelper mDbHelper; 

    public static final String TABLE_PASSWORD = "tbl_password"; 
    // columns 
    public static final String PASSWORD_ID = "_id"; 
    public static final String PASSWORD = "password"; 
    // create table string 
    private static final String CREATE_TABLE_PASSWORD = 
      "CREATE TABLE if not exists " + TABLE_PASSWORD + " (" + 
        PASSWORD_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + 
        PASSWORD + " TEXT NOT NULL);"; 

    public SQLiteDBAdapter(Context context) { 
     context = context.getApplicationContext(); 
    } 

    public SQLiteDatabase openDb() { 
     if (mDbHelper == null) { 
      mDbHelper = new DatabaseHelper(mContext); 
     } 
     return mDbHelper.getWritableDatabase(); 
    } 

    protected static class DatabaseHelper extends SQLiteOpenHelper { 
     // ------------------------------------------------------------------------------------------- 
     public DatabaseHelper(Context context) { 
      super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     } 
     // ------------------------------------------------------------------------------------------- 
     @Override 
     public void onCreate(SQLiteDatabase db) { 
      db.execSQL(CREATE_TABLE_PASSWORD); 
     } 
     // ------------------------------------------------------------------------------------------- 
     @Override 
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
      Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + 
        newVersion + ", which will destroy all old data"); 
      db.execSQL("DROP TABLE IF EXISTS routes"); 
      onCreate(db); 
     } 
    } 
} 

3) Расширить Sqlite объект для работы с таблицей (операции CRUD):/

public class PasswordDbAdapter extends SQLiteDBAdapter { 

    private SQLiteDatabase db; 

    // these are column corresponding indices 
    public static final int INDEX_PASSWORD_ID = 0; // an auto-increment 
    public static final int INDEX_PASSWORD = 1; 

    public PasswordDbAdapter(Context context) { 
     super(context); 
    } 

    public void addPassword(String password) { 
     db = openDb(); 
     ContentValues values = new ContentValues(); 
     values.put(PASSWORD, password); 
     db.insert(TABLE_PASSWORD, null, values); 
    } 

    public void updatePassword(String password) { 
     db = openDb(); 
     ContentValues values = new ContentValues(); 
     values.put(PASSWORD, password); 
     db.update(TABLE_PASSWORD, values, null); 
    } 

    public void deletePassword() { 
     db = openDb(); 
     db.delete(TABLE_PASSWORD, null, null); 
    } 

    public boolean isEmpty() { 
     db = openDb(); 
     boolean empty = true; 
     Cursor cur = db.rawQuery("SELECT COUNT(*) FROM " + TABLE_PASSWORD, null); 
     if (cur != null && cur.moveToFirst()) { 
      empty = (cur.getInt (0) == 0); 
     } 
     cur.close(); 
     return empty; 
    } 

    public Password fetchPassword() { // ok because there's only one password record 
     db = openDb(); 
     Cursor cursor = db.query(TABLE_PASSWORD, new String[]{PASSWORD_ID, PASSWORD}, 
       null, null, null, null, null, null); 
     if (cursor != null && 
      cursor.moveToFirst()) { 
      return new Password(
        cursor.getString(INDEX_PASSWORD_ID), 
        cursor.getInt(INDEX_PASSWORD)); 
     } 
     return null; 
    } 
} 

4) Наконец, сохранить обновление/извлечения passwor d:

public class MainActivity extends AppCompatActivity { 
    private PasswordDbAdapter passwordDB; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     ... 
     // initialize the password db 
     passwordDB = new PasswordDbAdapter(this); 

     // check if password record exists 
     if (passwordDB.isEmpty() { 
      // save a new copy 
      passwordDB.addPassword("the_password"); // more secure if it is saved encrypted 
     } else { 
      // update it 
      passwordDB.updatePassword("the_password"); 
     } 

    } 
    ... 
    public String fetchPassword() { 
     return passwordDB.fetchPassword(); // or first decrypt it, then return it 
    } 
} 
+0

Это НЕПРАВИЛЬНО .... прочитайте вопрос «Теперь для достижения уровня безопасности я удаляю пароль из общих настроек и использую синглтон, который поддерживается только во время сеанса приложения». Моя цель - сохранить его во время выполнения памяти и не сохраняются в общих привилегиях дискового хранилища. В любом случае вы никогда не должны хранить пароль в текстовом формате –

+0

Android-синглы могут быть очень проблематичными. Но см. Http://stackoverflow.com/questions/16517702/singleton-in-android. Теперь, касаясь использования Sqlite, моя рекомендация - хранить зашифрованный пароль. Еще проще, вы можете хешировать пароль и вместо этого использовать хэш. – nkmuturi

Смежные вопросы