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.数据库中只存储了加密后的信息

相关推荐
苹果醋31 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader1 小时前
深入解析 Apache APISIX
java·apache
了一li1 小时前
Qt中的QProcess与Boost.Interprocess:实现多进程编程
服务器·数据库·qt
菠萝蚊鸭2 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
码农君莫笑2 小时前
信管通低代码信息管理系统应用平台
linux·数据库·windows·低代码·c#·.net·visual studio
旭东怪2 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
007php0072 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程
∝请叫*我简单先生2 小时前
java如何使用poi-tl在word模板里渲染多张图片
java·后端·poi-tl
别致的影分身2 小时前
使用C语言连接MySQL
数据库·mysql
ssr——ssss2 小时前
SSM-期末项目 - 基于SSM的宠物信息管理系统
java·ssm