随机盐值实现密码的加密与验证

近日,在做完博客系统的项目之后发现在进行用户登录的时候对于密码的防护性不够严谨,可能会存在密码的安全问题,故本文将介绍如何使用【随机盐值】来实现密码的加密与解密

一、加密 & 代码解读

  • 首先我们来看到的是第一种【加盐加密】的方法,即为直接传入密码随机产生盐值来进行加密
java 复制代码
/**
 * 加盐加密
 *
 * @param password 明文密码
 * @return 加盐加密的密码
 */
public static String encrypt(String password) {
    // 1.产生盐值
    String salt = UUID.randomUUID().toString().replace("-", "");
    // 2.使用MD5(盐值+明文密码)得到加密的密码
    String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
    // 3.将盐值和加密的密码共同返回(合并盐值和加密密码)
    String dbPassword = salt + "$" + finalPassword;
    return dbPassword;
}

接下去我们来细致地解读一下这个加盐算法

  1. 首先我们使用工具类UUID中的randomUUID()方法,根据所传入的两个参数随机产生一个盐值
java 复制代码
// 1.产生盐值
String salt = UUID.randomUUID().toString().replace("-", "");
  1. 然后我们则使用工具类DigestUtils中的md5DigestAsHex()方法将随机生成的盐值进行拼接然后得到最后的加密后的密码
java 复制代码
// 2.使用MD5(盐值+明文密码)得到加密的密码
String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
  1. 最后,此方法会将所得到的盐值和最后的密码进行返回
java 复制代码
// 3.将盐值和加密的密码共同返回(合并盐值和加密密码)
String dbPassword = salt + "$" + finalPassword;

  • 接下去我们再来看看另一种的加密算法,不仅是传递所需要加密的密码,盐值也需要一并地传入
java 复制代码
/**
 * 加盐加密
 *
 * @param password 明文密码
 * @param salt     可传递盐值
 * @return 加盐加密的密码
 */
public static String encrypt(String password, String salt) {
    // 1.使用(盐值+明文密码)得到加密的密码
    String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
    // 2.将盐值和加密的密码共同返回(合并盐值和加密密码)
    String dbPassword = salt + "$" + finalPassword;
    return dbPassword;
}

💬那既然已经传入了盐值salt,那么除去第一步的盐值生成,其他都是一样的

二、验证 & 代码解读

  • 以下是对于用户所传递进来的密码进行验证的过程
java 复制代码
/**
 * 验证加盐加密密码
 *
 * @param password   明文密码(不一定对,需要验证明文密码)
 * @param dbPassword 数据库存储的密码(包含:salt+$+加盐加密密码)
 * @return true=密码正确
 */
public static boolean decrypt(String password, String dbPassword) {
    boolean result = false;
    if (StringUtils.hasLength(password) && StringUtils.hasLength(dbPassword) &&
            dbPassword.length() == 65 && dbPassword.contains("$")) { // 参数正确
        // 1.得到盐值
        String[] passwrodArr = dbPassword.split("\$");
        // 1.1 盐值
        String salt = passwrodArr[0];
//            // 1.2 得到正确密码的加盐加密密码
//            String finalPassword = passwrodArr[1];
        // 2.生成验证密码的加盐加密密码
        String checkPassword = encrypt(password, salt);
        if (dbPassword.equals(checkPassword)) {
            result = true;
        }
    }
    return result;
}

我们马上来解读一下

  1. 首先我们要先来进行参数校验,要检查的就是这两个参数是否存在,并且要检查从数据库中所取到的加盐后密码长度是否== 65,而且是否包含字符"$"
java 复制代码
if (StringUtils.hasLength(password) && StringUtils.hasLength(dbPassword) &&
        dbPassword.length() == 65 && dbPassword.contains("$")) { // 参数正确
  1. 因为所存入数据库的finalPasswordsalt + "$" + finalPassword;,所以我们要通过split()来取出取出和这个盐值
java 复制代码
// 1.得到盐值
String[] passwrodArr = dbPassword.split("\$");
// 1.1 盐值
String salt = passwrodArr[0];
  1. 最后,当我们得到这个盐值后,对用户所传递进来的密码进行一样的加盐加密,将得到后的结果与数据库中的密码进行比较,如果相同的话则进行标记,最后我们通过result来进行观察
java 复制代码
// 2.生成验证密码的加盐加密密码
String checkPassword = encrypt(password, salt);
if (dbPassword.equals(checkPassword)) {
    result = true;
}

三、测试观察

最后我们通过实体的用户注册登录来进行一下测试,观察是否可以达到加密验证

  • 首先看到当前系统中总共有两个用户,分别是【admin】和【zhangsan】
  • 然后我们去注册一个用户名为:lisi,并且密码为ls123的用户
  • 然后我们就可以看到数据库中多了一条用户名为:lisi,并且密码为ls123的用户
  • 接着我们就可以去进行登录了,输入刚才所注册的用户名和密码就可以,我们一起来调试着看看
  • 然后便很成功地登录进去了
  • 我们可以再来试试输错密码的可能性。很明显当密码输错的时候在进行验证的时候就会识别到了

以上就是有关随机盐值实现密码的加密与验证,希望本文对您有所帮助🌹

相关推荐
叶落阁主21 小时前
Tailscale 完全指南:从入门到私有 DERP 部署
运维·安全·远程工作
光影少年1 天前
async/await和Promise的区别?
前端·javascript·掘金·金石计划
用户908324602731 天前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
用户8307196840822 天前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解2 天前
Spring Boot 视图层与模板引擎
spring boot·后端
光影少年2 天前
在 React 中,什么情况下需要用 useCallback 和 useMemo?它们的区别是什么?
前端·react.js·掘金·金石计划
Java水解2 天前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
洋洋技术笔记2 天前
Spring Boot Web MVC配置详解
spring boot·后端
用户962377954483 天前
DVWA 靶场实验报告 (High Level)
安全
初次攀爬者3 天前
Kafka 基础介绍
spring boot·kafka·消息队列