Забыли пароль по электронной почте, используя SQLite - PullRequest
0 голосов
/ 23 сентября 2019

Есть ли способ сделать забытый пароль по электронной почте с помощью sqlite в Android Studio?Я видел только восстановление типа секретного ключа, но ничего при отправке электронной почты.Видел это с помощью огненной базы.Просто хотел узнать, возможно ли это в sqlite.

1 Ответ

0 голосов
/ 24 сентября 2019

Да, это возможно, ниже приведен базовый пример, который позволяет отправлять электронную почту с новым паролем сброса (он не выполняет генерацию или отправку электронной почты, а копирует ее, записывая вместо этого в журнал).

Сначала Помощник по базам данных (подкласс SQLiteOpenHelper), который также включает в себя процедуры безопасности: -

DatabaseHelper.java

public class DatabaseHelper extends SQLiteOpenHelper {

    public class DatabaseConstants {

        public static final String DBNAME = "mydatabase";
        public static final int DBVERSION = 1;

        public class UserTableConstants {

            public static final String TABLENAME = "user";
            public static final String USERID = BaseColumns._ID;
            public static final String USEREMAIL = "email";
            public static final String USERSALT = "salt";
            public static final String USERHASH= "hash";

            public static final String CRTSQL = "CREATE TABLE IF NOT EXISTS " +
                    TABLENAME + "("
                    + USERID + " INTEGER PRIMARY KEY, "
                    + USEREMAIL + " TEXT NOT NULL UNIQUE, "
                    + USERSALT + " TEXT NOT NULL, "
                    + USERHASH + " TEXT NOT NULL "
                    + ")";
        }
    }

    SQLiteDatabase mDB;

    public DatabaseHelper(Context context) {
        super(context, DatabaseConstants.DBNAME, null, DatabaseConstants.DBVERSION);
        mDB = this.getWritableDatabase();
    }

    /**
     * Called when the database is created for the first time. This is where the
     * creation of tables and the initial population of the tables should happen.
     *
     * @param db The database.
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DatabaseConstants.UserTableConstants.CRTSQL);
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public boolean addUser(String email, String password) {
        SaltandHash sah = new SaltandHash(password);
        ContentValues cv = new ContentValues();
        cv.put(DatabaseConstants.UserTableConstants.USEREMAIL,email);
        cv.put(DatabaseConstants.UserTableConstants.USERSALT,sah.getSalt());
        cv.put(DatabaseConstants.UserTableConstants.USERHASH,sah.getHash());
        return (mDB.insert(DatabaseConstants.UserTableConstants.TABLENAME,null,cv) > 0);
    }

    public boolean loginUser(String email, String password) {
        boolean rv = false;
        Cursor csr = mDB.query(
                DatabaseConstants.UserTableConstants.TABLENAME,
                null,
                DatabaseConstants.UserTableConstants.USEREMAIL+"=?",
                new String[]{email},
                null,null,null
        );
        if (csr.moveToFirst()) {
            rv = checkPassword(
                    password,
                    csr.getString(
                            csr.getColumnIndex(DatabaseConstants.UserTableConstants.USERSALT)
                    ),
                    csr.getString(
                            csr.getColumnIndex(DatabaseConstants.UserTableConstants.USERHASH)
                    )
            );
        }
        csr.close();
        return rv;

    }

    public boolean resetPassword(String email) {
        Cursor csr = mDB.query(
                DatabaseConstants.UserTableConstants.TABLENAME,
                null,
                DatabaseConstants.UserTableConstants.USEREMAIL + "=?",
                new String[]{email},
                null,null,null
        );
        int rowCount = csr.getCount();
        csr.close();
        if (rowCount != 1) return false;
        String newPassword = generateRandomPassword();
        SaltandHash sah = new SaltandHash(newPassword);
        ContentValues cv = new ContentValues();
        cv.put(DatabaseConstants.UserTableConstants.USERSALT,sah.getSalt());
        cv.put(DatabaseConstants.UserTableConstants.USERHASH,sah.getHash());
        int result = mDB.update(DatabaseConstants.UserTableConstants.TABLENAME,cv, DatabaseConstants.UserTableConstants.USEREMAIL +"=?",new String[]{email});
        if (result != 1) return false;
        Log.d("NEWPASSWORD","A new password has been sent to " + email + " the password is " + newPassword);
        // SEND THE EMAIL FROM HERE
        return true;
    }

    private boolean checkPassword(String password, String salt, String hash) {
        byte[] saltdecoded = android.util.Base64.decode(salt, android.util.Base64.DEFAULT);
        byte[] hashdecoded = android.util.Base64.decode(hash, android.util.Base64.DEFAULT);
        byte[] comprehash;

        KeySpec ks = new PBEKeySpec(password.toCharArray(),saltdecoded,65536,128);
        try {
            SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            comprehash = skf.generateSecret(ks).getEncoded();
        } catch (Exception e) {
            return false;
        }
        return Arrays.equals(hashdecoded,comprehash);
    }


    /**
     * SaltandHash class for generating and storing a salt and hash from
     * the given password.
     */
    private class SaltandHash {
        private byte[] salt;
        private byte[] hash;
        private boolean worked = true;

        SaltandHash(String password) {
            this.salt = new SecureRandom().generateSeed(32);
            KeySpec ks = new PBEKeySpec(
                    password.toCharArray(),
                    salt,
                    65536,
                    128
            );
            try {
                SecretKeyFactory skf =
                        SecretKeyFactory.getInstance(
                                "PBKDF2WithHmacSHA1"
                        );
                hash = skf.generateSecret(ks).getEncoded();
            } catch (Exception e) {
                worked = false;
            }
        }

        private String getHash(){
            return android.util.Base64.encodeToString(this.hash, android.util.Base64.DEFAULT);
        }

        private String getSalt() {
            return android.util.Base64.encodeToString(this.salt, android.util.Base64.DEFAULT);
        }

        private boolean ifSaltandHashOK() {
            return worked;
        }
    }

    private String generateRandomPassword() {
        int password_length = 32;
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.@#?abcdefghijklmnopqrstuvwxyz";
        Random rnd = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i=0; i < password_length; i++ ) {
            int pos = rnd.nextInt(chars.length());
            sb.append(chars.substring(pos,pos+1));
        }
        return sb.toString();
    }
}
  • Это управляеттаблица, содержащая электронную почту пользователя, соль и хеш (НЕ сам пароль).

  • Включает методы для: -

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

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

И затем, наконец, пытается войти в систему с исходным паролем, который не удается (так как пароль был сброшен).

MainActivity.java

public class MainActivity extends AppCompatActivity {

    DatabaseHelper mDBHlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDBHlpr = new DatabaseHelper(this);

        // Add the user
        String userEmail = "Fred@FredsEmail.com";
        mDBHlpr.addUser(userEmail,"mypassword");

        loginUser(userEmail,"mypassword");
        loginUser(userEmail,"notmypassword");

        // Reset the password according to the email
        resetPassword(userEmail);
        resetPassword("hacker@hacker.mail.com");
        resetPassword(userEmail);
        resetPassword(userEmail);
        resetPassword(userEmail);
        loginUser(userEmail,"mypassword");
    }

    private void resetPassword(String email) {
        String TAG = "RESETPWRSLT";
        if (mDBHlpr.resetPassword(email)) {
            Log.d(TAG,"Password was reset and an email sent to " + email);
        } else {
            Log.d(TAG,"WARNING an attempt to reset a password failed for the email " + email);
        }
    }

    private void loginUser(String email, String password) {
        String TAG = "LOGINRSLT";
        if (mDBHlpr.loginUser(email,password)) {
            Log.d(TAG,"Login in attamept successful for " + email);
        } else {
            Log.d(TAG,"FAILED LOGIN IN ATTEMPT for " + email);
        }
    }
}

Результат

Журнал, когда запускается вышеуказанное, содержит (обратите внимание, что пароли сброса устанавливаются случайным образом): -

2019-09-24 14:04:23.761  D/LOGINRSLT: Login in attamept successful for Fred@FredsEmail.com
2019-09-24 14:04:24.413  D/LOGINRSLT: FAILED LOGIN IN ATTEMPT for Fred@FredsEmail.com
2019-09-24 14:04:25.036  D/NEWPASSWORD: A new password has been sent to Fred@FredsEmail.com the password is WooFd5FvPgswTGCTzVmDomrXEzKpTy39
2019-09-24 14:04:25.036  D/RESETPWRSLT: Password was reset and an email sent to Fred@FredsEmail.com
2019-09-24 14:04:25.036  D/RESETPWRSLT: WARNING an attempt to reset a password failed for the email hacker@hacker.mail.com
2019-09-24 14:04:25.659  D/NEWPASSWORD: A new password has been sent to Fred@FredsEmail.com the password is qcwDMFDTaoYc4hosuSw6BMRet4Wq2RG#
2019-09-24 14:04:25.659  D/RESETPWRSLT: Password was reset and an email sent to Fred@FredsEmail.com
2019-09-24 14:04:26.282  D/NEWPASSWORD: A new password has been sent to Fred@FredsEmail.com the password is KlTk6uRaliLzQ3IC1Yqql9XV2xioEi#v
2019-09-24 14:04:26.282  D/RESETPWRSLT: Password was reset and an email sent to Fred@FredsEmail.com
2019-09-24 14:04:26.908  D/NEWPASSWORD: A new password has been sent to Fred@FredsEmail.com the password is voHtOZz7nAw?enAIErYW7KsimA2k@JQ0
2019-09-24 14:04:26.909  D/RESETPWRSLT: Password was reset and an email sent to Fred@FredsEmail.com
2019-09-24 14:04:27.533  D/LOGINRSLT: FAILED LOGIN IN ATTEMPT for Fred@FredsEmail.com
...