加密方式介绍
- 对称加密:加密和解密使用的相同的密钥,常见的对称加密算法有:DES、3DES
- 非对称加密:加密和解密使用的密钥不同,常见的非对称加密算法有:RSA
- 加密:使用私钥加密
- 解密:使用公钥解密
- 消息摘要: 消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,只有相同的原文经过消息摘要算法之后,才能得到相同的密文,所以消息摘要通常用来校验原文的真伪。常用的消息摘要算法有:MD5、SHA、MAC
- MD5加密
MD5加密是一种常见的加密方式,我们经常用在保存用户密码和关键信息上。
MD5加密特点:
- 针对不同长度待加密的数据、字符串等等,其都可以返回一个固定长度的MD5加密字符串。(通常32位的16进制字符串);
- 加密过程几乎不可逆,除非用一个庞大的Key-Value数据库来进行碰撞破解,否则几乎无法解开。
- 运算简便,且可实现方式多样,通过一定的处理方式也可以避免碰撞算法的破解。
对于一个固定的字符串。数字等等,MD5加密后的字符串是固定的,也就是说不管MD5加密多少次,都是同样的结果。
1 使用JDK自带的API实现MD5util工具类进行加密
封装执行加密的工具类(MD5Util.java)可以直接在addUSer()方法运行前进行加密
public class MD5Util {
/**
* 针对明文字符串执行MD5加密
* @param source
* @return
*/
public static String encode(String source) {
// 1.判断明文字符串是否有效
if (source == null || "".equals(source)) {
throw new RuntimeException("用于加密的明文不可为空");
}
// 2.声明算法名称
String algorithm = "md5";
// 3.获取MessageDigest对象
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 4.获取明文字符串对应的字节数组
byte[] input = source.getBytes();
// 5.执行加密
byte[] output = messageDigest.digest(input);
// 6.创建BigInteger对象
int signum = 1;
BigInteger bigInteger = new BigInteger(signum, output);
// 7.按照16进制将bigInteger的值转换为字符串
int radix = 16;
String encoded = bigInteger.toString(radix).toUpperCase();
return encoded;
}
}
2. 使用Spring的DigestUtils工具类
测试代码如下:
void testMD5() {
String pwd = "123456";
// 基于spring框架中的DigestUtils工具类进行密码加密
String hashedPwd1 = DigestUtils.md5DigestAsHex((pwd).getBytes());
System.out.println(hashedPwd1);
}
怕不够安全可以进行“加盐”
处理:
void testMD5() {
String pwd = "123456";
String salt = UUID.randomUUID().toString();
// 基于spring框架中的DigestUtils工具类进行密码加密
String hashedPwd1 = DigestUtils.md5DigestAsHex((pwd + salt).getBytes());
System.out.println(hashedPwd1);
}
也可以进行多次加盐
void testMD5() {
String pwd = "123456";
String salt = UUID.randomUUID().toString();
// 基于spring框架中的DigestUtils工具类进行密码加密
String hashedPwd1 = DigestUtils.md5DigestAsHex((pwd + salt).getBytes());
hashedPwd1 = DigestUtils.md5DigestAsHex((hashedPwd1 + salt).getBytes());
hashedPwd1 = DigestUtils.md5DigestAsHex((hashedPwd1 + salt).getBytes());
// ... 可使用循环加盐
System.out.println(hashedPwd1);
}
3创建连接数据库的工具类
package com.example.util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
public class JDBCUtils {
private static DataSource dataSource =null;
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
//创建连接池
static{
//读取属性文件
Properties prop = new Properties();
//System.out.println("prop1:"+prop);
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
try {
prop.load(is);
//System.out.println("prop2:"+prop);
//根据属性文件创建连接池
dataSource = DruidDataSourceFactory.createDataSource(prop);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据库连接
public static Connection getConnection(){
//先从ThreadLocal中获取
Connection conn = threadLocal.get();
//如果没有连接,说明是该线程中第一次访问,
if(conn ==null ){
try {
//从连接池中获取一个连接
conn = dataSource.getConnection();
//放入到threadLocal中
threadLocal.set(conn);
} catch (Exception e) {
e.printStackTrace();
}
}
//返回连接
return conn;
}
//关闭数据库连接(如果采用了连接池,就是归还连接)
public static void releaseConnection(){
//从threadLocal中获取
Connection conn = threadLocal.get();
try {
if(conn !=null){
conn.close(); //不是物理关闭,而是放入到连接池中,置为空闲状态
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//这个语句不要少
//threadLocal.set(null);//连接已经放回连接池,不使用了。ThreadLocal也不需要再保存了
threadLocal.remove();
}
}
}
4创建BaseDao
package com.example.dao;
import com.example.util.JDBCUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* 功能:对数据库的任意表格进行增删改查
* ① 增删改
* ② 三个查询
*/
public class BaseDao<T> {
//2. 创建QueryRunner对象
private QueryRunner runner=new QueryRunner();
/**
* 功能:对数据库进行增删改的操作
* @param sql
* @param params
* @return
*/
public boolean update(String sql,Object...params){
//1. 获得数据库连接
Connection connection = JDBCUtils.getConnection();
//3. 执行
try {
int update = runner.update(connection, sql, params);
if(update>0)
return true;
} catch (SQLException e) {
e.printStackTrace();
}finally {
//4. 释放资源
JDBCUtils.releaseConnection();
}
return false;
}
/**
* 功能:查询多条数据
* @param type
* @param sql
* @param params
* @return
*/
public List<T> getBeanList(Class type,String sql,Object...params){
//1. 获得数据库连接
Connection connection = JDBCUtils.getConnection();
//3. 执行
try {
return runner.query(connection, sql, new BeanListHandler<T>(type), params);
} catch (SQLException e) {
e.printStackTrace();
}finally{
//4. 释放资源
JDBCUtils.releaseConnection();
}
return null;
}
/**
* 功能:查询一条结果
* @param type
* @param sql
* @param params
* @return
*/
public T getBean(Class type,String sql,Object...params){
//1. 获得数据库连接
Connection connection = JDBCUtils.getConnection();
//3. 执行
try {
return runner.query(connection,sql,new BeanHandler<T>(type),params);
} catch (SQLException e) {
e.printStackTrace();
}finally{
//4. 释放资源
JDBCUtils.releaseConnection();
}
return null;
}
/**
* 功能:查询一个结果
* @param sql
* @param params
* @return
*/
public Object getObject(String sql,Object...params){
//1. 获得数据库连接
Connection connection = JDBCUtils.getConnection();
//3. 执行
try {
return runner.query(connection,sql,new ScalarHandler(),params);
} catch (SQLException e) {
e.printStackTrace();
}finally{
//4. 释放资源
JDBCUtils.releaseConnection();
}
return null;
}
}
5创建注册RegistServlet.java
package com.example.servlet;
import com.example.bean.User;
import com.example.dao.UserDao;
import com.example.dao.impl.UserDaoImpl;
import com.example.util.MD5Util;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet(name = "RegistServlet", value = "/RegistServlet")
public class RegistServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1获得请求参数
Map<String, String[]> parameterMap = request.getParameterMap();
User user=new User();
try {
BeanUtils.populate(user,parameterMap);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
//2 处理注册业务
//将信息添加到数据库,需要考虑密码加密问题。
UserDao userDao=new UserDaoImpl();
System.out.println("密码设置为="+user.getPassword());
String encode=MD5Util.encode(user.getPassword());//encode是加密后的密码
user.setPassword(encode);
System.out.println("加密成功="+encode);
boolean b=userDao.addUser(user);
System.out.println("添加成功");
//3 响应(页面跳转)
if (b){
request.getRequestDispatcher("/pages/user/regist_success.html").forward(request,response);
}else {
request.getRequestDispatcher("/pages/user/regist_error.html").forward(request,response);
}
}
}
前端表单
<form action="RegistServlet" @submit="checkAll">
<div class="form-item">
<div>
<label>用户名称:</label>
<input type="text" placeholder="请输入用户名" name="username" @blur="checkUsername" v-model="username" />
</div>
<span class="errMess">{{usernameErrMsg}}</span>
</div>
<div class="form-item">
<div>
<label>用户密码:</label>
<input type="password" placeholder="请输入密码" name="password" @blur="checkPassword" v-model="password"/>
</div>
<span class="errMess">{{passwordErrMsg}}</span>
</div>
<div class="form-item">
<div>
<label>确认密码:</label>
<input type="password" placeholder="请输入确认密码" @blur="checkConfirmPassword" v-model="confirmPassword"/>
</div>
<span class="errMess">{{confirmPasswordErrMsg}}</span>
</div>
<div class="form-item">
<div>
<label>用户邮箱:</label>
<input type="text" placeholder="请输入邮箱"name="email" @blur="checkEmail" v-model="email"/>
</div>
<span class="errMess">{{emailErrMsg}}</span>
</div>
<div class="form-item">
<div>
<label>验证码:</label>
<div class="verify">
<input type="text" placeholder="" />
<img src="static/img/code.bmp" alt="" height="50px"/>
</div>
</div>
<span class="errMess">请输入正确的验证码</span>
</div>
<button class="btn">注册</button>
</form>
测试
数据库表: