目录
项目概述与加密需求
项目名称:基于校园平台的设备报修系统
主要技术:JFinal 5.0.2 +MyBatis+Enjoy 3.5.6
功能实现:该系统采用三层架构与MVC框架模式,JFinal处理控制器,MyBatis处理数据持久层与枚举类型转换,Enjoy处理表示层。
功能简要:校园师生可直接通过账号登录系统,完成对设备的修改查询及报修,同时产生新的工单并完成分配,并且可以对维修人员及基础设备进行管理,设备保修操作同时支持pc与移动端操作。
加密需求
- 用户密码需先进行加密操作再存入数据库
- 用户请求更改密码时,系统向用户发送的邮件需对用户信息进行加密
- 将用户登录信息存入Cookie中,需对用户密码进行加密
MD5——处理用户存入数据库中的密码
什么是MD5
MD5消息摘要算法,属Hash算法一类。MD5算法对输入任意长度的消息进行运行,产生一个128位的消息摘要(32位的数字字母混合码)。
主要特点
MD5是一种非对称的加密算法,不可逆,相同数据的MD5值肯定一样,不同数据的MD5值不一样。
- 压缩性:任意长度的数据,算出的MD5值长度都是固定的(相当于超损压缩)。
- 容易计算:从原数据计算出MD5值很容易。
- 抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
- 弱抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
- 强抗碰撞:想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。
数据库中的应用
2010年后,达成了一个共识,就是需将密码以加密后的方式存入数据库中,原因是数据库并不是绝对安全的,破解登录密码后便可以查看所有的信息。
import com.jfinal.kit.HashKit;
public class Test {
public static void main(String[] args) {
String str = "我爱Java";
String pwd = HashKit.md5(str);
System.out.println(pwd);
//执行结果
//3a17003d62e5e62051714ac7f6762524
}
}
项目应用
用户完成登录操作,相当于数据库中一条查询语句;用户修改密码,相当于数据库中的一条查询语句。对于用户注册、修改密码的操作,仅需将密码加密后存储进数据库即可;对于查询语句,需要对两个字段进行判断,仅需在传入查询的值前对其进行加密即可。
// 根据手机号码和登录密码查找用户
public User getUserByPhoneNumberAndPwd(String loginPhoneNumber, String loginPassword) throws Exception{
try (SqlSession ss = MyBatisUtils.getSqlSession()){
UserMapper mapper = ss.getMapper(UserMapper.class);
User user = mapper.selectUserByPhoneAndPwd(loginPhoneNumber,
HashKit.md5(loginPassword));
if(user != null) {
//深克隆 修改用户最后登录时间
User userr = user.clone();
userr.setLastLoginTime(new Date());
int row = mapper.updateUser(userr);
if(row == 1) {
ss.commit();
}
}
return user;
} catch (Exception e) {
e.printStackTrace();
throw new Exception("登录失败,失败原因是:" + e.getCause() != null ?
e.getCause().getMessage() : e.getMessage());
}
}
AES
什么是AES
高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法对称加密算法也就是加密和解密用相同的密钥。
工具类AesKit&Base64Kit应用
Base64是一种编码方式,可将字节转换成字符串。
AesKit静态方法 | Base64Kit应用 |
byte[] encrypt(String 要加密的内容,String 32位秘钥) | encode(byte[] 要编码的内容) |
String decrypt(byte[] 要解密的内容,String 32位秘钥) | decode(String 要解码的内容) |
项目应用
// 重新设置用户的新密码
public boolean resetUserNewLoginPassword(String id, String newPwd) throws Exception {
try (SqlSession ss = MyBatisUtils.getSqlSession()){
UserMapper mapper = ss.getMapper(UserMapper.class);
User user = new User();
String userId = AesKit.decryptToStr(Base64Kit.decode(id), key);
System.out.println(Integer.parseInt(userId));
user.setUserId(Integer.parseInt(userId));
String pwd = HashKit.md5(newPwd);
user.setLoginPassword(pwd);
int row = mapper.updateUser(user);
if(row == 1) {
ss.commit();
return true;
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
存储密码时 ,需要在拦截器中进行解密,而在真实情况中无需再用Aes进行解密,这样可以避免打开浏览器的人知道密码的位数。
public class CookieInViewInterceptor implements Interceptor {
final private static String key = "zhizihuakaiyakai333zhizihuakaiya";
@Override
public void intercept(Invocation inv) {
if(inv.getActionKey().equals("/passport/login") || inv.getActionKey().equals("/passport")) {
String phoneNumber = inv.getController().getCookie("cookiePhoneNumber");
String pwd = inv.getController().getCookie("cookiePassword");
if(pwd != null && pwd != "") {
String passwd = AesKit.decryptToStr(Base64Kit.decode(pwd), key);
inv.getController().set("cookiePassWord", passwd);
}
inv.getController().set("cookiePhoneNumber", phoneNumber);
}
inv.invoke();
}
}