加密方式介绍

  • 对称加密:加密和解密使用的相同的密钥,常见的对称加密算法有:DES、3DES
  • 非对称加密:加密和解密使用的密钥不同,常见的非对称加密算法有:RSA
  • 加密:使用私钥加密
  • 解密:使用公钥解密
  • 消息摘要: 消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,只有相同的原文经过消息摘要算法之后,才能得到相同的密文,所以消息摘要通常用来校验原文的真伪。常用的消息摘要算法有:MD5、SHA、MAC

- MD5加密

MD5加密是一种常见的加密方式,我们经常用在保存用户密码和关键信息上。
MD5加密特点:

  1. 针对不同长度待加密的数据、字符串等等,其都可以返回一个固定长度的MD5加密字符串。(通常32位的16进制字符串);
  2. 加密过程几乎不可逆,除非用一个庞大的Key-Value数据库来进行碰撞破解,否则几乎无法解开。
  3. 运算简便,且可实现方式多样,通过一定的处理方式也可以避免碰撞算法的破解。
    对于一个固定的字符串。数字等等,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>
测试

java如何避免密码明文使用 java登录密码加密_sql


数据库表:

java如何避免密码明文使用 java登录密码加密_java_02