13.MD5对用户密码进行加密

时间:2021-11-10 02:59:27

MD5概述

用户名密码保存在客户端是一种十分危险的行为。所以需要进行加密后保存。

其中MD5就是一种比较常用的加密算法。

与其说MD5算法是一种加密算法,不如说是一种数据指纹(数据摘要)算法。

其特点如下:

任意大小的二进制数经过MD5计算后都能得到一个独一无二的128位二进制数。

不同的数据算出的MD5绝对不相同。

相同的数据算出的MD5一定相同。

只能有明文算出密文,密文是永远也无法算成明文的。

MD5大量应用于计算机中。如数据库中保存的密码通常都是经过MD5加密后的数据。如用户下载文件时可以进行MD5校验防止数据被篡改。

在记住用户名案例中,我们可以使用MD5进行加密后再保存在客户端,从而保证数据安全。

在数据库中保存的密码也不宜直接存储为明文。也要经过MD5加密后存储。

第一步:编写一个MD5的工具类

package cn.bingou.util;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; public class MD5Utils { public static String md5(String plainText){
// 用来保存加密后的密文的数组
byte[] secreBytes = null; try {
// 将明文转成byte数组并进行加密,获得密文数组
secreBytes = MessageDigest.getInstance("md5").digest(
plainText.getBytes());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("没有md5这个算法");
}
// 将二进制数组转车过16进制表示的字符串
String md5code = new BigInteger(1, secreBytes).toString(16);
//128位2进制数组转成16进制时,可能不足32位
//在字符串前面补0,使所有的字符串长度一定是32位
for(int i=0; i<32-md5code.length();i++){
md5code = "0"+md5code;
}
return md5code;
}
}

第二步:调用工具类

注册用户的代码中调用MD5的工具类,将明文密码变为MD5密文。

package cn.bingou.web;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import cn.bingou.domain.User;
import cn.bingou.factory.BaseFactory;
import cn.bingou.service.UserService;
import cn.bingou.service.UserServiceImpl;
import cn.bingou.util.JDBCUtils;
import cn.bingou.util.MD5Utils;
import cn.bingou.util.WebUtils; public class RegistServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException { // // 1.请求乱码问题
// // 请求乱码-POST请求
// req.setCharacterEncoding("utf-8");
// // 应答乱码问题
// resp.setContentType("text/html;charset=utf-8"); // 2.接收表单参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String password2 = req.getParameter("password2");
String nickname = req.getParameter("nickname");
String email = req.getParameter("email");
String valistr = req.getParameter("valistr"); // 3.验证表单
// 1)非空验证 if(WebUtils.isEmpty(username)){ // 用户名为空验证
// 向request作用域中添加错误提示信息
req.setAttribute("errMsg", "用户名不能为空!");
// 将请求转发给regist.jsp,forward():请求转发
req.getRequestDispatcher("/regist.jsp").forward(req, resp);
// 如果用户输入为空,直接返回
return;
}
if(WebUtils.isEmpty(password)){ // 密码为空验证
req.setAttribute("errMsg", "密码不能为空!");
req.getRequestDispatcher("/regist.jsp").forward(req, resp);
return;
}
if(WebUtils.isEmpty(nickname)){ // 昵称为空验证
req.setAttribute("errMsg", "昵称不能为空!");
req.getRequestDispatcher("/regist.jsp").forward(req, resp);
return;
}
if(WebUtils.isEmpty(email)){ // 邮箱为空验证
req.setAttribute("errMsg", "邮箱不能为空!");
req.getRequestDispatcher("/regist.jsp").forward(req, resp);
return;
} // 2)密码一致验证
if(!password.equals(password2)){
// 如果密码与确认密码不一样,则输出错误
req.setAttribute("errMsg", "密码不一致");
req.getRequestDispatcher("/regist.jsp").forward(req, resp);
return;
} // 3)邮箱格式验证
// abc@123.163.com
String reg="^\\w+@\\w+(\\.\\w+)+$";
if(!email.matches(reg)){
req.setAttribute("errMsg", "邮箱格式不符");
req.getRequestDispatcher("/regist.jsp").forward(req, resp);
return;
} // 4)用户名是否存在
UserService userService=BaseFactory.getFactory().getInstance(UserService.class);
boolean flag=userService.hasUsername(username);
if(flag){//用户名已存在
// 向request作用域中添加错误提示信息
req.setAttribute("errMsg", "用户名已存在");
// 将请求转发给regist.jsp
req.getRequestDispatcher("/regist.jsp").forward(req, resp);
return;
} // 5)验证码验证
if(WebUtils.isEmpty(valistr)){ // 验证码为空验证
req.setAttribute("errMsg", "验证码不能为空!");
req.getRequestDispatcher("/regist.jsp").forward(req, resp);
return;
} else{
// 验证码不为空,执行验证码内容验证
// 获取保存在session中的正确验证码
HttpSession session=req.getSession(false);// 如果当前Session没有就为null
boolean flag1=true; // 默认验证码没有问题
if(session==null && session.getAttribute("text")==null){
// 没有session对象,或者session中没有正确的验证码文本
flag1=false;
}else{
String text=(String) session.getAttribute("text");
if(!valistr.equalsIgnoreCase(text)){
// 用户输入的文本和正确文本不一致
flag1=false;
}
}
if(flag1==false){
// 向request作用域中添加错误提示信息
req.setAttribute("errMsg", "验证码错误");
// 将请求转发给regist.jsp
req.getRequestDispatcher("/regist.jsp").forward(req, resp);
return;
}
} // 将密码进行MD5加密
password=MD5Utils.md5(password);
// 4.数据存入数据库
User user=new User(-1, username, password, nickname, email); boolean flag1=userService.registUser(user);
if(flag1){// 保存成功-提示成功信息,定时刷新到首页
resp.getWriter().write("<h1 style='text-align:center;color:red'>恭喜您,注册成功!3秒后自动跳转首页</h1>");
// 实现定时刷新
resp.setHeader("refresh", "3;url="+req.getContextPath()+"/index.jsp");
}else{
req.setAttribute("errMsg", "注册出现异常,请稍后重试...");
req.getRequestDispatcher("/regist.jsp").forward(req, resp);
return;
}
} public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
} }

用户登陆的时候也要将输入的密码转换成MD5加密之后的密文,与数据库里面的密文进行比对。

package cn.bingou.web;

import java.io.IOException;
import java.net.URLEncoder; import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import cn.bingou.domain.User;
import cn.bingou.exception.MsgException;
import cn.bingou.factory.BaseFactory;
import cn.bingou.service.UserService;
import cn.bingou.util.MD5Utils; public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException { // 获取web.xml中配置的字符集
String encode=this.getServletContext().getInitParameter("encode");
// // 1.处理乱码-请求乱码
// // POST请求乱码
// req.setCharacterEncoding(encode);
// 2.接收请求参数
String username=req.getParameter("username");// 使用request.getParameter可以获得表单传过来的值
String password=req.getParameter("password");
String remname=req.getParameter("remname");
// 3.表单验证
// 将用户的明文密码转成MD5加密后的密码
password=MD5Utils.md5(password);
// 4.执行逻辑
// 1)记住用户名
// 判断用户是否勾选了记住用户名
if(remname != null && "true".equals(remname)){
// 勾选了记住用户名
// 创建一个保存用户名的Cookie
// URLEncoder.encode用来对一个字符串进行编码
Cookie cookie=new Cookie("rename",URLEncoder.encode(username,encode));
// 设置一个有效时间
cookie.setMaxAge(60*60*24*30);
// 手动设置一个路径 web应用的根路径
// EasyMall被配置成了虚拟主机的默认web应用
// 导致req.getContextPath()返回 ""
// setPath("")-》无效的,所以setPath(""+"/")->有效
cookie.setPath(req.getContextPath()+"/");
// 将Cookie添加到Response中
resp.addCookie(cookie);
}else{
// 如果没有勾选记住用户名-删除之前保存的Cookie
Cookie cookie=new Cookie("remname","");
cookie.setPath(req.getContextPath()+"/");
cookie.setMaxAge(0);// 删除当前Cookie
resp.addCookie(cookie);
}
// 2)登陆
// 判断用户的用户名和密码是否正确
UserService userServlet=BaseFactory.getFactory().getInstance(UserService.class); User user=null;
try {
user=userServlet.login(username, password);
} catch (MsgException e) {
e.printStackTrace();
req.setAttribute("errMsg", e.getMessage());
req.getRequestDispatcher("/login.jsp").forward(req, resp);
return;
} if(user != null){
// 登录成功-向session中添加登录状态
req.getSession().setAttribute("user", username);
System.out.println(user.getUsername());
System.out.println(username);
// 重定向到首页
resp.sendRedirect(req.getContextPath()+"/index.jsp");
}else{
//添加错误提示信息,并返回login.jsp
req.setAttribute("errMsg", "用户名或密码错误");
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
} public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
} }