Spring Boot:从明文存储->MD5->MD5加盐

密码安全演进:从明文到MD5加盐

        明文存储

        在CRUD中没有任何加秘密操作,数据库中是明文存储的,一旦电脑遭到劫持,密码统统不安全。

        MD5加密

        MD5 就像给数据做 “数字指纹” 的工具,不管你输入的是一段文字、一张图片还是一个大文件(不管原始数据有多长),它都能输出一个固定长度的 “指纹”—— 通常是 32 位的十六进制字符串。具体怎么做呢?首先会给原始数据补点内容,比如先加个 “1”,再用很多 “0” 凑长度,最后加上原始数据的长度,确保总长度能分成一个个 512 位的小块;接着准备 4 个固定的初始值当 “临时容器”;然后把分好的小块挨个拿来处理,每块都要经过 64 步复杂的位运算(比如移位、对比、合并这些操作),不断更新那 4 个 “容器” 里的值;等所有小块都处理完,把最后 4 个 “容器” 的值拼起来,再转成十六进制字符串,就是这段数据的 MD5 “指纹” 了。它的特点是没法从 “指纹” 反推出原始数据,而且很难找到两个不同数据算出一样的 “指纹”,所以常用在检查文件有没有被改、存简单密码(非特别敏感的场景)这些地方。(AI生成)

        使用方法:创建一个MD5工具类:

public class MD5Utils {
    public static String md5(String plainText) {
        byte[] secretBytes = null;
        try {
            // 1. 获取MD5摘要算法实例
            secretBytes = MessageDigest.getInstance("md5").digest(
                    plainText.getBytes());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有这个md5算法!");
        }
        // 2. 将字节数组转换为十六进制字符串
        String md5code = new BigInteger(1, secretBytes).toString(16);
        // 3. 补齐32位长度(不足的前面补0)
        for (int i = 0; i < 32 - md5code.length(); i++) {
            md5code = "0" + md5code;
        }
        return md5code;
    }
}

        接着在登录,注册,修改密码,忘记密码等用到密码的地方调用该方法即可。如:

/**
    * 登录
    */
    @IgnoreAuth
    @RequestMapping(value = "/login")
    public R login(String username, String password, String captcha, HttpServletRequest request) {
        // 对输入的密码进行MD5加密
        String encryptedPassword = MD5Utils.md5(password);

        YonghuEntity yonghu = yonghuService.selectOne(new EntityWrapper<YonghuEntity>().eq("username", username));
        // 修改密码比较逻辑
        if(yonghu==null || !yonghu.getPassword().equals(encryptedPassword))
            return R.error("账号或密码不正确");
        else if(yonghu.getStatusTypes() == 2)
            return R.error("该账号已被冻结");
        String token = tokenService.generateToken(yonghu.getId(),username, "yonghu", "用户");
        R r = R.ok();
        r.put("token", token);
        r.put("role","用户");
        r.put("username",yonghu.getYonghuName());
        r.put("tableName","yonghu");
        r.put("userId",yonghu.getId());
        return r;
    }

    /**
    * 注册
    */
    @IgnoreAuth
    @PostMapping(value = "/register")
    public R register(@RequestBody YonghuEntity yonghu, HttpServletRequest request) {
        Wrapper<YonghuEntity> queryWrapper = new EntityWrapper<YonghuEntity>()
                .eq("username", yonghu.getUsername())
                .or()
                .eq("yonghu_phone", yonghu.getYonghuPhone())
                .or()
                .eq("yonghu_id_number", yonghu.getYonghuIdNumber())
                ;
        YonghuEntity yonghuEntity = yonghuService.selectOne(queryWrapper);
        if(yonghuEntity != null)
            return R.error("账户或者联系方式或者身份证号已经被使用");

        // 对密码进行MD5加密
        yonghu.setPassword(MD5Utils.md5("123456")); // 默认密码加密
        yonghu.setNewMoney(0.0);
        yonghu.setStatusTypes(1);
        yonghu.setCreateTime(new Date());
        yonghuService.insert(yonghu);

        return R.ok();
    }

    /**
     * 重置密码
     */
    @GetMapping(value = "/resetPassword")
    public R resetPassword(Integer  id, HttpServletRequest request) {
        YonghuEntity yonghu = yonghuService.selectById(id);
        // 对密码进行MD5加密
        yonghu.setPassword(MD5Utils.md5("123456"));
        yonghuService.updateById(yonghu);
        return R.ok();
    }

	/**
	 * 修改密码
	 */
    @GetMapping(value = "/updatePassword")
    public R updatePassword(String  oldPassword, String  newPassword, HttpServletRequest request) {
        YonghuEntity yonghu = yonghuService.selectById((Integer)request.getSession().getAttribute("userId"));
        if(newPassword == null){
            return R.error("新密码不能为空") ;
        }
        // 对旧密码和新密码进行MD5加密后比较
        if(!yonghu.getPassword().equals(MD5Utils.md5(oldPassword))){
            return R.error("原密码输入错误");
        }
        if(yonghu.getPassword().equals(MD5Utils.md5(newPassword))){
            return R.error("新密码不能和原密码一致") ;
        }
        // 新密码加密存储
        yonghu.setPassword(MD5Utils.md5(newPassword));
        yonghuService.updateById(yonghu);
        return R.ok();
    }

        MD5加盐加密

        "加盐"(Salt)是一种增强安全性的手段,通过在原始数据中加入随机字符串再进行哈希计算,能有效防止彩虹表(预计算哈希值的字典)攻击。

        只需要在原有的工具类修改:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

//不建议修改名字,改完还得修改方法里的调用
public class MD5Utils {
    
    // 生成随机盐值
    public static String generateSalt() {
        // 使用安全的随机数生成器
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[16]; // 16字节的盐值
        random.nextBytes(salt);
        // 转换为Base64字符串方便存储
        return Base64.getEncoder().encodeToString(salt);
    }
    
    // 带盐值的MD5加密
    public static String md5WithSalt(String plainText, String salt) {
        try {
            // 1. 创建MD5算法实例
            MessageDigest md = MessageDigest.getInstance("MD5");
            
            // 2. 将盐值转换为字节数组并更新摘要
            md.update(salt.getBytes());
            
            // 3. 将明文转换为字节数组并更新摘要
            byte[] digest = md.digest(plainText.getBytes());
            
            // 4. 将字节数组转换为十六进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                // 转换为两位十六进制数,不足两位前面补0
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5算法不存在", e);
        }
    }
    
}

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值