28.<Spring博客系统④(使用MD5摘要算法对数据库密码进行加密)>

密码算法简介

**1.对称加密算法:**加密和解密算法一样

**2.非对称加密算法:**公钥加密、私钥解密

**3.摘要算法:**不能解密,不可逆

简单介绍了解一下:

一、对称密码算法

是指加密秘钥和解密秘钥相同的密码算法. 常见的对称密码算法有: AES, DES, 3DES,RC4, RC5, RC6 等.
二、非对称密码算法

是指加密秘钥和解密秘钥不同的密码算法. 该算法使⽤⼀个秘钥进行加密, 用另外一个秘钥进行解密.

加密秘钥可以公开,又称为 公钥

解密秘钥必须保密,又称为 私钥

常见的非对称密码算法有: RSA, DSA, ECDSA, ECC 等
三、摘要算法

1.任意长度的输入消息数据转化为固定长度的输出数据的一种密码算法.。

2.摘要算法是不可逆的, 也就是无法解密.。

通常用来检验数据的完整性的重要技术, 即对数据进行哈希计算然后比较摘要值,,判断是否一致。

常见的摘要算法有: MD5, SHA系列(SHA1, SHA2等), CRC(CRC8, CRC16,CRC32)

一、MD5摘要算法(非常简单的加密方式)

我们的博客系统采用摘要算法 MD5 进行操作。

其实严格来说摘要算法 主要是做校验使用。

明文 -> 摘要算法 → 另外字符串

接收到的明文 -> 摘要算法 → 另外字符串

如果两个字符串相等。救认为接收到的明文是正确的。
特点

1.不可逆

2.不同长度的字符串,经过MD5之后。得到字符串长度相同。

3.相同的字符串,经过MD5处理后。得到的字符串是相同的。(无论什么语言、什么平台实现)

有些网站会对MD5解密。(对于简单字符串)

因此我们在原始明文密码上。加上一个随机的盐值(相对复杂)。之后(明文+盐值)这个字符串就无法进行解密了。
盐值(salt)

盐值:就是相对复杂的字符串。

**加密逻辑:**明文 + 盐值 = 复杂的明文 再通过MD5进行加密 → 得到密文

校验逻辑:

(用户输入的明文+盐值) 通过MD5进行加密 → 得到密文

如果这两个密文相同。就认为用户输入的明文和注册时的明文密码是相同的。

**数据库需要保存 :**盐值和密文

验证方式:

待验证的明文+这个随机盐值,进行MD5加密。和数据库的密文进行对比。

实现步骤:

一、用户注册

1.生成随机盐值

2.用户明文密码+随机盐值,通过MD5进行加密。

3.保存 随机盐值 和密文。

二、用户登录

1.获取用户注册时的随机盐值

2.待验证的明文+第一步的随机盐值,通过MD5进行加密

3.判断第二步的密文和用户注册时数据库中存的密文是否一样。
UUID

不会重复

通常是和userId对应。但并不完全。

UUID是根据设备来的。

一个userId可能有多个UUID

java 复制代码
System.out.println(UUID.randomUUID());

打印示例:

3c7719cd-b790-40c8-abb9-49a5545574dd

二、MD5使用示例

2.1 得到密文

数据库中存储(盐值+密文)

java 复制代码
    /**
     * 得到密文
     */
     @Test
    public void encrypt(){
        String password = "123456";
        //明文
        String md5Str = DigestUtils.md5DigestAsHex(password.getBytes());
        //对字符串 password 进行 MD5 加密
        //并将结果转换为一个 32 位的十六进制字符串
        //将字符串 password 转换为字节数组。
        System.out.println(md5Str);
        String salt = UUID.randomUUID().toString().replace("-","");
         System.out.println(salt);
         //得到盐值
         // .toString(): 将UUID 转换为字符串。
         //.replace("-", ""):去掉字符串中的所有连字符(-),使生成的盐值成为一个连续的字符串。
         String securityPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());
         //得到密文
         String finalPassword = salt +securityPassword;
         System.out.println(finalPassword);
         //最终数据库存储的内容
     }

2.2解密校验

java 复制代码
    /**
     * 解密
     */
    @Test
    public void verify(){
        String inputPassword ="123456";
        String sqlPassword = "587bd5b3bf7f42ca9e0bce3da50e516f9096e954d0eb8ff2bd68e8b87c49afc6";
        //sqlPassword 是 salt + md5(salt + md5(salt_password))
        if(sqlPassword == null || sqlPassword.length()!=64){
            System.out.println("校验失败");
        }
        String salt = sqlPassword.substring(0,32);
        String secretPassword = DigestUtils.md5DigestAsHex((salt + inputPassword).getBytes());
        String findPassword = salt +secretPassword;
        if(findPassword.equals(sqlPassword)){
            System.out.println("校验成功");
        }else {
            System.out.println("校验失败!");
        }
    }

三、将MD5加密应用到博客系统

在utils包中创建SecurityUtils类

3.1.根据明文进行加密

java 复制代码
    public static String encrypt(String password){
        String md5Str = DigestUtils.md5DigestAsHex(password.getBytes());
        String salt = UUID.randomUUID().toString().replace("-","");
        String securityPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());
        return salt+securityPassword;
    }

3.2密码校验

java 复制代码
    public static boolean verify(String inputPassword,String sqlPassword){
        if(sqlPassword == null || sqlPassword.length()!=64){
            log.error("数据库中密码格式错误!");
            return false;
        }
        String salt = sqlPassword.substring(0,32);
        String secretPassword = DigestUtils.md5DigestAsHex((salt + inputPassword).getBytes());

        return sqlPassword.equals(salt+secretPassword);
    }

3.3更改UserController类

java 复制代码
    @RequestMapping("/login")
    public Result login(String userName, String password){
        //1.参数校验
        //2.对密码进行校验
        //3.如果校验成功,生成token
        if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){
            return Result.fail("用户名或密码不能为空!");
        }
        UserInfo userInfo = userService.queryUserByName(userName);
        if(userInfo == null || userInfo.getId() <= 0){
            return Result.fail("用户不存在");
        }
//        if(!password.equals(userInfo.getPassword())){
//            return Result.fail("密码错误!");
//        }
        if(!SecurityUtils.verify(password,userInfo.getPassword())){
            return Result.fail("密码错误!");
        }
        //密码正确
        Map<String,Object> claim = new HashMap<>();
        claim.put(Constant.USER_CLAIM_Id,userInfo.getId());
        claim.put(Constant.USER_CLAIM_NAME,userInfo.getUserName());
        return Result.success(JWTUtils.gentToken(claim));
    }

3.4修改数据库中的密码

通过之前测试类中我们生成的findPassword。将他替换数据库中的密码。

密码都是123456。

但是在数据库中,我们是看不出来的

常见错误:

1.加密和校验的逻辑不一样。

数据库中存储的信息是(盐值+md5(salt+明文))。

注意 盐值 和 密文的 顺序。

2.数据库忘了修改密码

3.数据库中只存储了加密后的信息

相关推荐
阿华的代码王国10 分钟前
【Bug合集】——Java大小写引起传参失败,获取值为null的解决方案
java·开发语言·springboot
redemption_228 分钟前
mybatis 动态SQL语句
java·jvm·mybatis
北执南念34 分钟前
Mybatis-Plus 多租户插件&属性自动赋值
java·mybatis
Atlasgorov38 分钟前
JAVA_单例模式
java·开发语言·单例模式
BestandW1shEs38 分钟前
设计模式的基本概述
java·设计模式
G皮T39 分钟前
【设计模式】入门 23 种设计模式(代码讲解)
java·设计模式·软件工程·创建型模式·行为型模式·结构型模式
南宫生1 小时前
力扣-Hot100-链表其一【算法学习day.34】
java·学习·算法·leetcode·链表
2402_857583491 小时前
Spring Boot框架:电商开发的新趋势
数据库·spring boot·后端
打码人的日常分享1 小时前
【资料】网络安全风险评估报告,风险管理报告,网络安全风险管理计划,网络安全网络安全能力验证报(Word原件)
数据库·安全·web安全·需求分析·规格说明书
奔跑的废柴1 小时前
LeetCode 18. 四数之和 Java题解
java·算法·leetcode