目录
五、数据库加密
1、数据库加密:
将密码存入数据库中时,不能直接以明文的形式存入,而是要经过某种方法加密之后再存入数据库。
数据库加密的其中一种方法是使用md5方法进行加密
案例:对加密数据库的增加和登录
BaseDao及用到的MD5加密方法:拿来直接用
public class MD5Util {
//这里主要是遍历8个byte,转化为16位进制的字符,即0-F
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
//这里是针对单个byte,256的byte通过16拆分为d1和d2
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
/**
* 返回大写MD5
*
* @param origin
* @param charsetname
* @return
*/
private static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString.toUpperCase();
}
//加密时,不使用随机的盐,相同的数加密出来的结果是相同的
public static String MD5EncodeUtf8(String origin) {
origin = origin + "salt";
return MD5Encode(origin, "utf-8");
}
//方法重载,加密时也添加加密使用的盐,用随机数当加密的盐,即使密码相同,加密的结果也是不相同的。
public static String MD5EncodeUtf8(String origin,String salt) {
origin = origin + salt;
return MD5Encode(origin, "utf-8");
}
private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
public static void main(String[] args) {
String password="207ACD61A3C1BD506D7E9A4535359F8A";
String pass="123456";// 输入密码
String s = MD5EncodeUtf8(pass);
System.out.println(s.equals(password));
}
}
实体类:
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
private Integer id;
private String username;
private String password;
}
dao接口:
public interface IUserDao {
//查找数据库中所有数据
List<Map<String,Object>> findAll();
//通过名字查找用户
List<Map<String,Object>> findUserByName(String username);
//添加用户
int addUser(User user);
}
dao实现:
public class UserDaoImpl extends BaseDao implements IUserDao {
//查找t_user表格中的所有信息
@Override
public List<Map<String, Object>> findAll() {
String sql = "select * from t_user";
return query(sql);
}
//通过该用户的用户名查找该用户的所有信息
@Override
public List<Map<String, Object>> findUserByName(String username) {
String sql = "select * from t_user where username=?";
List<Map<String, Object>> query = query(sql, username);
return query;
}
//用于添加(注册)用户
@Override
public int addUser(User user) {
String sql = "insert into t_user(username,password,salt) values(?,?,?)";
//UUID(Universally Unique Identifier)是通用唯一识别码的缩写,是一种软件建构的标准
//利用uuid方式生成随机数
UUID uuid = UUID.randomUUID();
//将该随机数以字符串形式输出,作为加密所使用的盐
// String s = uuid + "";这种方式通过和字符串进行运算也能强制转换为字符串格式
String salt = uuid.toString();
//利用得到的盐通过MD5进行加密,得到加密后的密码,user.getPassword是明文输入的密码
String newPassword = MD5Util.MD5EncodeUtf8(user.getPassword(), salt);
//将用户名,加密的密码以及加密时使用的盐存入到数据库中
int i = addOrUpdate(sql, user.getUsername(), newPassword, salt);
//返回受影响的行数
return i;
}
}
登录页面的servlet:
@WebServlet(name = "LoginServlet", value = "/loginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//先将请求和响应的格式设置为utf-8格式,否则中文名字加载不出来
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//通过request请求获取表单中所有信息(这里是用户名和密码)
Map<String, String[]> parameterMap = req.getParameterMap();
System.out.println(parameterMap);
//将获取的信息转为实体类(key-value形式)
//获取实体类
User user = new User();
try {
//转化为实体类
BeanUtils.populate(user,parameterMap);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
System.out.println(user);
IUserDao iUserDao = new UserDaoImpl();
List<Map<String, Object>> userByName = iUserDao.findUserByName(user.getUsername());
//如果有该用户名,再检查密码是否正确
if (userByName.size()>0){
//要检查密码是否正确,要把输入的密码以相同的加密方式进行加密后比较
//拿到数据库中的密码(因为在数据库中,用户名是不能重复的,
// 所以查找的结果集合中只会有一条数据,所以查找结果值的某个属性时只需要get(0)就可以定位到该数据)
String password = userByName.get(0).get("password").toString();
System.out.println(password);
//拿到数据库中加密时使用的盐
String salt = userByName.get(0).get("salt").toString();
System.out.println(salt);
//用数据库中的盐对用户输入的密码进行加密
String md5Password = MD5Util.MD5EncodeUtf8(user.getPassword(), salt);
System.out.println(md5Password);
//将加密过的密码与数据库中的加密密码进行比较
if (md5Password.equals(password)){
//如果密码也正确,则跳转到展示信息界面
System.out.println("成功了");
resp.sendRedirect("userServlet");
}else {
System.out.println("失败了");
//密码不正确,则重新输入信息
resp.sendRedirect("index.jsp");
}
}else{
//如果该用户名不存在,则提示重新登录(跳转到登录页面)
resp.sendRedirect("index.jsp");
}
}
}
查询全部用户的servlet:
@WebServlet(name = "UserServlet", value = "/userServlet")
public class UserServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
IUserDao iUserDao = new UserDaoImpl();
List<Map<String, Object>> all = iUserDao.findAll();
System.out.println(all);
HttpSession session = req.getSession();
session.setAttribute("allUser",all);
resp.sendRedirect("user.jsp");
// req.setAttribute("allUser",all);
// //请求转发,将信息携带
// req.getRequestDispatcher("user.jsp").forward(req,resp);
}
}
添加用户的servlet:
@WebServlet(name = "addUserServlet", value = "/addUserServlet")
public class addUserServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//将请求和响应的编码格式设置为utf-8
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//获取注册页面的请求携带的信息
Map<String, String[]> parameterMap = req.getParameterMap();
User user = new User();
try {
//将信息转化为实体类
BeanUtils.populate(user,parameterMap);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
IUserDao iUserDao = new UserDaoImpl();
//调用实现类中的添加方法,将用户名,加密密码,以及盐放入数据库
int i = iUserDao.addUser(user);
if (i>0){
//如果添加成功,受影响的行数大于1,则跳到登录界面
resp.sendRedirect("index.jsp");
}else {
//如果失败,依旧还是注册页面
resp.sendRedirect("addUser.jsp");
}
}
}
登录页面代码(.jsp)
<h1>登录界面</h1>
<a href="addUser.jsp">添加用户</a>
<form action="loginServlet" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
添加用户界面代码(.jsp)
<h1>注册用户</h1>
<form action="addUserServlet" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="注册">
</form>
展示所有用户代码(.jsp)
<h1>展示信息</h1>
<table border="1" cellspacing="0">
<tr>
<th>id</th>
<th>名字</th>
<th>加密密码</th>
<th>盐</th>
</tr>
<c:forEach items="${allUser}" var="u">
<tr>
<td>${u.id}</td>
<td>${u.username}</td>
<td>${u.password}</td>
<td>${u.salt}</td>
</tr>
</c:forEach>
</table>