手机安全卫士07-手机防盗之进入限制
最后更新于:2022-04-01 16:16:28
上次写到在进入手机但·防盗界面时需要有密码限制,首先第一次进入时会弹出对话框提示用户设置密码;再次进入时会要求用户输入密码;这次来具体实现上述功能。
### 首次登录,设置密码
首先,我们的密码是保存在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)
惊呆了,有木有!
所以,以后在重要的网站设置密码时一定要设的复杂一点!!!