【问题标题】:Android. How to save user name and password after the app is closed?安卓。应用关闭后如何保存用户名和密码?
【发布时间】:2014-03-08 23:06:25
【问题描述】:

我正在编写一个包含登录详细信息(用户名和密码)的应用程序。
我想这样当用户关闭应用程序并稍后再次启动时,他/她不必再次输入他/她的用户名和密码。

到目前为止,这是我的代码。它似乎不记得密码和用户名,不幸的是我:

protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);

    mPrefs = getSharedPreferences(PREFS, 0);
    final CheckBox rememberMeCbx = (CheckBox)findViewById(R.id.saveLoginCheckBox);

    boolean rememberMe = mPrefs.getBoolean("rememberMe", false);



    if (android.os.Build.VERSION.SDK_INT > 9)
    {
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
    }
    mXmlRpcClient = new XMLRPCClient(mXmlRpcUri);

    // Set up the login form.
    //mUsername = getIntent().getStringExtra(EXTRA_EMAIL);
    mUsernameView = (EditText) findViewById(R.id.username);
    mUsernameView.setText(mUsername);

    mPasswordView = (EditText) findViewById(R.id.password);
    mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
                @Override
                public boolean onEditorAction(TextView textView, int id,
                        KeyEvent keyEvent) {
                    if (id == R.id.login || id == EditorInfo.IME_NULL) {
                        attemptLogin();
                        return true;
                    }
                    return false;
                }
            });

    mLoginFormView = findViewById(R.id.login_form);
    mLoginStatusView = findViewById(R.id.login_status);
    mLoginStatusMessageView = (TextView) findViewById(R.id.login_status_message);

    findViewById(R.id.sign_in_button).setOnClickListener
    (
            new View.OnClickListener()
            {
                @Override
                public void onClick(View view) 
                {
                    if(rememberMeCbx.isChecked())
                    {
                        attemptLogin(); //function to check if fields are filled correctly
                        saveLoginDetails();
                    }
                    else
                    {
                        attemptLogin();
                        removeLoginDetails();
                    }

                }
            });

    if(rememberMe == true)
    {
        //get previously stored login details
        String login = mPrefs.getString("mUsername", null);
        String upass = mPrefs.getString("mPassword", null);

        if(login != null && upass != null)
        {
            //fill input boxes with stored login and pass
            EditText loginEbx = (EditText)findViewById(R.id.username);
            EditText passEbx = (EditText)findViewById(R.id.password);
            loginEbx.setText(login);
            passEbx.setText(upass);

            //set the check box to 'checked'                
            rememberMeCbx.setChecked(true);
        }
    }
}



/**
 * Represents an asynchronous login/registration task used to authenticate
 * the user.
 */
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Void... params) {
        try {
            mSessionID = (String)mXmlRpcClient.call(mLoginFuncName, mUsername, mPassword);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    protected void onPostExecute(final Boolean success) {
        mAuthTask = null;
        showProgress(false);

        if (success) {
            finish();
            Intent intent = new Intent(LoginActivity.this, MainWindow.class);
            intent.putExtra("SessionID", mSessionID);
            intent.putExtra("XmlRpcUrl", mXmlRpcUrl);
            intent.putExtra("LoginFuncName", mLoginFuncName);
            intent.putExtra("LogoutFuncName", mLogoutFuncName);
            intent.putExtra("GetDevicesFuncName", mGetDevicesFuncName);
            intent.putExtra("SendPositionFuncName", mSendPositionFuncName);
            intent.putExtra("GetSavedTripFunc", mGetSavedTripFunc);             
            startActivity(intent);
        } else {
            mPasswordView
                    .setError(getString(R.string.error_incorrect_password));
            mPasswordView.requestFocus();
        }
    }


}

private void saveLoginDetails()
{
    //fill input boxes with stored login and pass
    EditText loginEbx = (EditText)findViewById(R.id.username);
    EditText passEbx = (EditText)findViewById(R.id.password);
    String login = loginEbx.getText().toString();
    String upass = passEbx.getText().toString();

    Editor e = mPrefs.edit();
    e.putBoolean("rememberMe", true);
    e.putString("login", login);
    e.putString("password", upass);
    e.commit();
}

private void removeLoginDetails()
{
    Editor e = mPrefs.edit();
    e.putBoolean("rememberMe", false);
    e.remove("login");
    e.remove("password");
    e.commit();
}

}

你能告诉我我的代码有什么问题吗?我该如何改进它,以便在应用程序关闭并再次打开后保存和检索用户名和密码?

【问题讨论】:

  • 在活动onPause() 中保存了Preference 的数据,并在活动onResume() 中加载该数据
  • 所以你的意思是我应该把我的 saveLoginDetails() 方法放在 onPause() 和 "if(rememberMe == true)" 中检查 onResume() ?
  • 您应该从复选框 onCheckedChangeListener 中获取记住我的值,并且要保存和获取登录信息,您应该使用 SharedPreferences ,请参阅本教程以了解如何从首选项中保存/检索数据:android-ios-tutorials.com/54/…

标签: android user-interface passwords save


【解决方案1】:

我建议,您将登录详细信息保存在一个简单加密的文件中。

密码 = 1234qwer 加密密码 = 149250351452q113w119e101r114

OnStop 保存登录数据

OnStart 读取登录数据

【讨论】:

  • 加密不是这个问题的答案。他问的是如何保存凭据而不是如何保护它...
【解决方案2】:

我高度不推荐你的逻辑!我建议您使用AccountManager API 来验证和存储用户凭据,或者编写您自己的客户经理,始终使用仅存储您的身份验证令牌的 AccountManager

也可以通过 root 访问客户经理的数据!

根据您的逻辑,至少尝试以安全的方式使用 SharedPreferences,否则通过 root 访问,我们可以从移动设备获取 SharedPreferences 数据!

【讨论】:

  • 你将如何实现这个?
  • 使用 scottyab:secure-preferences 或只搜索如何使用自定义 Google 客户经理逻辑,有许多示例可用!
  • LOG_TAG 客户经理的数据也可以通过root访问,不安全。您需要我们加密。
  • @T.Dimitrov 非常真实!现在基于房间的共享偏好可通过加密获得更高的性能并支持缓存!
【解决方案3】:

到目前为止,我认为您的代码是正确的,但您不知道在哪里实现它。

所以应该有一个点您的登录成功并且您想在您的应用中打开另一个Activity,为此您必须调用Intent

因此,您需要做的就是在成功登录时触发Intent,您可以像这样调用saveLoginDetails() 方法。

if(*successful login condition*){
    Intent intent=new Intent(CurrentActivity.this,NextActivity.class);
    saveLoginDetails();
    startActivity(intent);
}

并且每当用户注销时,您都可以实现您的removeLoginDetails() 方法。

希望对您有所帮助...干杯... :)

【讨论】:

    【解决方案4】:

    试试这个方法:先定义Preferences

    private static final String PREFS_NAME = "preferences";
    private static final String PREF_UNAME = "Username";
    private static final String PREF_PASSWORD = "Password";
    
    private final String DefaultUnameValue = "";
    private String UnameValue;
    
    private final String DefaultPasswordValue = "";
    private String PasswordValue;
    

    还有onPause()

    @Override
    public void onPause() {
        super.onPause();
        savePreferences();
    
    }
    

    还有onResume()

    @Override
    public void onResume() {
        super.onResume();
        loadPreferences();
         }
    

    这里是savePreferences()

    private void savePreferences() {
        SharedPreferences settings = getSharedPreferences(PREFS_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
    
        // Edit and commit
        UnameValue = edt_username.getText();
        PasswordValue = edt_password.getText();
        System.out.println("onPause save name: " + UnameValue);
        System.out.println("onPause save password: " + PasswordValue);
        editor.putString(PREF_UNAME, UnameValue);
        editor.putString(PREF_PASSWORD, PasswordValue);
        editor.commit();
    }
    

    这里是loadPreferences()

    private void loadPreferences() {
    
        SharedPreferences settings = getSharedPreferences(PREFS_NAME,
                Context.MODE_PRIVATE);
    
        // Get value
        UnameValue = settings.getString(PREF_UNAME, DefaultUnameValue);
        PasswordValue = settings.getString(PREF_PASSWORD, DefaultPasswordValue);
        edt_username.setText(UnameValue);
        edt_password.setText(PasswordValue);
        System.out.println("onResume load name: " + UnameValue);
        System.out.println("onResume load password: " + PasswordValue);
    }
    

    【讨论】:

    • 嗯,这看起来很有希望,但我有一个复选框,所以如果复选框被选中,我想保存详细信息,如果不是,则不保存
    • @user3182266 共享偏好是方式
    • @user3182266 然后你需要存储支票簿状态并加载它并检查它。就是这样
    • 我建议在存储密码等时使用 MODE_PRIVATE。此外,在使用返回 String 的 getString() 后无需使用 .toString() 方法 :)
    • @Paradox 当您将信息保存在共享首选项文件中时,如果您的手机以某种方式被植根,则可以访问这些文件。如果您没有服务器并且可以采用访问令牌方法,我会建议您提供您识别用户并存储它的访问令牌,至少您应该在共享首选项之前使用加密。 androidluckyguys.wordpress.com/2017/09/12/… 看看,如果你有时间研究这个话题。客户经理也不是 100% 安全的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 2012-03-03
    • 1970-01-01
    • 2011-02-04
    • 1970-01-01
    • 1970-01-01
    • 2016-02-03
    相关资源
    最近更新 更多