💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
上次写到在进入手机但·防盗界面时需要有密码限制,首先第一次进入时会弹出对话框提示用户设置密码;再次进入时会要求用户输入密码;这次来具体实现上述功能。 ### 首次登录,设置密码 首先,我们的密码是保存在SharePreference中的”password”字段里的,在登录时后台需要校验该字段是否已经设置了密码,若未设置则弹出对话框让用户设置,否则要用户输入密码进入手机防盗界面; - **校验是否设置了密码** ~~~ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sp = getSharedPreferences("config", Context.MODE_PRIVATE); // 判读用户是否已经设置了密码 if (isPwdSetup()) { Log.i(TAG, "设置了密码,弹出输入密码的对话框"); } else { Log.i(TAG, "未设置密码,弹出设置密码对话框"); showFirstEntryDialog(); } } /** * 检查sharedpreference中是否有密码的设置 * * @return */ private boolean isPwdSetup() { String password = sp.getString("password", null); if (password == null) { return false; } else { if ("".equals(password)) { return false; } else { return true; } } } ~~~ - **showFirstEntryDialog(),弹出用户设置密码对话框** ~~~ /** * 第一次进入程序时弹出的设置密码的对话框 * 使用自定义对话框样式 */ private void showFirstEntryDialog() { dialog = new Dialog(this, R.style.MyDialog); // dialog.setContentView(R.layout.first_entry_dialog);// 设置要显示的内容 View view = View.inflate(this, R.layout.first_entry_dialog, null); et_pwd = (EditText) view.findViewById(R.id.et_first_entry_pwd); et_pwd_confirm = (EditText) view.findViewById(R.id.et_first_entry_pwd_confirm); Button bt_confirm = (Button) view.findViewById(R.id.bt_first_dialog_confirm); Button bt_cancel = (Button) view.findViewById(R.id.bt_first_dialog_cancel); // 设置按钮对应的点击事件 bt_confirm.setOnClickListener(this); bt_cancel.setOnClickListener(this); dialog.setContentView(view); dialog.setCanceledOnTouchOutside(false);// 设置dialog不可以点击其他地方时消失 dialog.setCancelable(false);// 设置dialog不可以点返回键时消失 dialog.show(); } ~~~ - **用户输入后,后台对用户的输入进行处理** ~~~ @Override public void onClick(View view) { switch(view.getId()){ // 点击取消 case R.id.bt_first_dialog_cancel: dialog.dismiss(); break; case R.id.bt_first_dialog_confirm: String pwd = et_pwd.getText().toString().trim(); String pwd_confirm = et_pwd_confirm.getText().toString().trim(); // 输入的密码中包好空值 if("".equals(pwd) || "".equals(pwd_confirm)){ Toast.makeText(getApplicationContext(), "输入不能为空!", Toast.LENGTH_LONG).show(); return; }else{ if(pwd.equals(pwd_confirm)){ Editor editor = sp.edit(); editor.putString("password", pwd); editor.commit(); } // 两次输入不一致 else{ Toast.makeText(getApplicationContext(), "两次输入密码不相同!", Toast.LENGTH_LONG).show(); return; } } dialog.dismiss(); break; } } ~~~ ### 效果如下: 初次进入手机防盗界面: ![](image/d41d8cd98f00b204e9800998ecf8427e.png) 未输入时点击确定: ![](image/d41d8cd98f00b204e9800998ecf8427e.png) 两次输入密码不相同: ![](image/d41d8cd98f00b204e9800998ecf8427e.png) ### 再次登录,输入密码 - **弹出对话框样式:normal_entry_dialog.xml** ~~~ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="300dip" android:layout_height="280dip" android:gravity="center_horizontal" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登录" android:textColor="@color/textcolor" android:textSize="24sp" /> <LinearLayout android:layout_width="300dip" android:layout_height="wrap_content" android:background="#ffc8c8c8" android:orientation="vertical" > <EditText android:id="@+id/et_normal_entry_pwd" android:layout_width="300dip" android:layout_height="wrap_content" android:hint="请输入密码" android:password="true" /> </LinearLayout> <LinearLayout android:layout_width="300dip" android:layout_height="50dip" android:gravity="center" android:orientation="horizontal" > <Button android:id="@+id/bt_normal_dialog_confirm" android:layout_width="140dip" android:layout_height="40dip" android:background="@drawable/button_background" android:text="确定" android:textColor="#ffffffff" /> <Button android:id="@+id/bt_normal_dialog_cancel" android:layout_width="140dip" android:layout_height="40dip" android:layout_marginLeft="3dip" android:background="@drawable/button_background" android:text="取消" /> </LinearLayout> </LinearLayout> ~~~ - **showNormalEntryDialog方法** ~~~ /** * 正常登录的对话框 * */ private void showNormalEntryDialog() { dialog = new Dialog(this, R.style.MyDialog); View view = View.inflate(this, R.layout.normal_entry_dialog, null); et_pwd = (EditText) view.findViewById(R.id.et_normal_entry_pwd); Button bt_confirm = (Button) view.findViewById(R.id.bt_normal_dialog_confirm); Button bt_cancel = (Button) view.findViewById(R.id.bt_normal_dialog_cancel); // 设置按钮对应的点击事件 bt_confirm.setOnClickListener(this); bt_cancel.setOnClickListener(this); dialog.setContentView(view); dialog.setCanceledOnTouchOutside(false);// 设置dialog不可以点击其他地方时消失 // dialog.setCancelable(false);// 设置dialog不可以点返回键时消失 dialog.show(); } ~~~ - **按键处理:** ~~~ @Override public void onClick(View view) { switch(view.getId()){ case R.id.bt_normal_dialog_cancel: dialog.dismiss(); break; case R.id.bt_normal_dialog_confirm: String input_pwd = et_pwd.getText().toString(); if("".equals(input_pwd)){ Toast.makeText(getApplicationContext(), "输入不能为空!", Toast.LENGTH_LONG).show(); return; }else{ String password = sp.getString("password", ""); if(!password.equals(input_pwd)){ Toast.makeText(getApplicationContext(), "输入密码不正确,请重新输入!", Toast.LENGTH_LONG).show(); et_pwd.selectAll();// 用户输入错误后,对文本进行全选,方便用户进行删除重新输入 return; } } Log.i(TAG, "加载手机防盗主界面"); dialog.dismiss(); break; } } ~~~ ### 效果如下: ![](image/d41d8cd98f00b204e9800998ecf8427e.png) ![](image/d41d8cd98f00b204e9800998ecf8427e.png) ### 密码加密存储 目前我们的密码存储都是以明文存储在SharePreference中的,因此有点Android开发基础的人都可以获取到我们设置的密码。 考虑使用加密算法对密码加密后进行存储。 使用JavaSe提供的MessageDigest类进行加密。MessageDigest支持的加密算法包括:MD5、SHA-1、SHA-256。 ~~~ package com.liuhao.mobilesafe.util; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5Encoder { public static String encode(String pwd) { try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] bytes = md.digest(pwd.getBytes()); StringBuffer sb = new StringBuffer(); for (byte b : bytes) { String str = Integer.toHexString(0xff & b);// byte是八位字节存储的,转化为16进制数,直接与11111111相与 if (str.length() == 1) { sb.append("0" + str); } else { sb.append(str); } } return sb.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); throw new RuntimeException("不存在加密算法"); } } } ~~~ 这样在存储密码时调用encode()方法即可对密码进行存储。在读取时也要用加密后的密文与已存储的进行对比。 ~~~ editor.putString("password", MD5Encoder.encode(pwd)); if(!password.equals(MD5Encoder.encode(input_pwd))){ Toast.makeText(getApplicationContext(), "输入密码不正确,请重新输入!", Toast.LENGTH_LONG).show(); et_pwd.selectAll();// 用户输入错误后,对文本进行全选,方便用户进行删除重新输入 return; } ~~~ 其实我们仅仅简单的一次加密也是很不保险的,虽说从算法实现上来说md5加密是不可逆的,但是有些“别有用心”的人,竟然将所有可预见的字符串对应的密文都算出来了,真是。。。 比如这个网站:[http://www.cmd5.com/](http://www.cmd5.com/) ![](image/d41d8cd98f00b204e9800998ecf8427e.png) 惊呆了,有木有! 所以,以后在重要的网站设置密码时一定要设的复杂一点!!!