7.14 注册登录如何安全传输密码?如何安全保存密码?SpringBoot实战项目手把手教你

CSDN成就一亿技术人

文章目录

  • 前言
  • 一、回顾简易的注册登录的问题
  • 二、必须做的
  • 三、方案设计
  • 四、落地
    • 4.1 引入hutool工具包
    • 4.2 hutool RSA加密解密
    • 4.3 hutool MD5加密
  • 五、注册接口升级 - 项目实战 手把手
    • 5.1 Web层配置注入RSA
    • 5.2 Service层使用RSA+MD5
  • 最后


前言

在前面的章节中,我们实现了简易的注册和登录功能,其它功能,像验证码、限流等或许你稍微研究一下都能找到解决方案,但有一个点你可能不那么容易搞定,那就是注册登录密码如何安全传输?
可以肯定的是:密码一定需要加密,一定不能明文传输!但加密算法怎么选?密码又要怎么安全保存?
如果你没有一些项目经验,估计有点棘手,最后还会感觉不那么保险。难者不会, 会者不难!
基于此,我今天决定写一篇简短的博文,手把手教你在SpringBoot实战项目中解决密码传输和密码保存的问题!
最后看完本文,你也看看你们的项目是否安全传输密码,是否安全保存密码!

之前讲过的注册和登录接口相关博文:

登录接口:3-3. SpringBoot项目集成【用户身份认证】实战 【全流程篇】基于JWT+双重检查的登录+登出+拦截器

注册接口:5.4 如何在Mybatis中使用insert标签并返回主键id?-- 教你通用做法


一、回顾简易的注册登录的问题

回顾一下之前写的流程:

注册:前端:MD5(password),后端:存储前端传入的密码!

登录:前端:MD5(password),后端:将前端传入的密码,与数据库保存的密码做匹配,匹配成功则登录成功!

看出来问题了吗?

如果是内部系统,部署在内网上,大家都是合法调用,那应该会相安无事!

但如果是部署到互联网上,那随时可能面临恶意调用的风险,后端既没有对密码的有校性做校验,也没有对密码的合法性做验证,说白了,后端连密码的控制权都没有,黑客传个明文的123456你一点办法都没有!


二、必须做的

认识到问题就等于解决了一半!

  • 第一,注册时的用户填密码绝对不可以直接明文传输到后端,前端必须加密,还必须支持让后端可以解密,为什么?
    因为后端需要对密码有效性做校验,例如:8-16位字符,必须包含大、小写字母及数字

  • 第二,后端对有效性校验通过以后,必须保存不能解密的密码为什么?
    如果数据库保存的密码能解密,那么开发人员,DBA,黑客等,是不是都有可能看到用户的密码?所以,安全的做法是:数据库保存的是不可解密的密码!


三、方案设计

  • 针对第一点,我们可以采用AESRSA等加密算法,相对安全又可以解密,我推荐是RSA,因为它是非对称加密!非对称的意思是指加密和解密的秘钥是不同的!
    值得说的是,RSA加密算法的安全性是较高的,非常值得信赖,位数越长越安全,没有秘钥破解非常困难!
    另外,由于AES是对称加密,前端加密与后端解密秘钥相同,所以这个秘钥保存在哪里也是一个问题,如何防止秘钥泄露也是一个问题!因为拿到这唯一的秘钥就可以解密了!!!而使用RSA加密算法,即使公钥泄露也不怕,因为RSA是非对称加密,公钥加密,私钥才可以解密!而私钥保存在后端呢,所以安全性更高一些!

  • 针对第二点,保存不可解密的密码,众所周知的是MD5,只要你的密码不是太简单,就很难被暴力破解!妥妥滴~


四、落地

4.1 引入hutool工具包

我这里使用hutool提供的现成的加密方法,先在父项目pom.xml dependencyManagement.dependencies引入依赖:

<dependency>
    <groupId>cn.hutoolgroupId>
    <artifactId>hutool-allartifactId>
    <version>5.8.12version>
dependency>

再到common子项目引入依赖(不需要版本号)

4.2 hutool RSA加密解密

  • 初始化RSA类

    RSA rsa = new RSA();
    
  • 生成公钥、私钥

    String privateKeyBase64 = rsa.getPrivateKeyBase64();
    String publicKeyBase64 = rsa.getPublicKeyBase64();
    
  • 使用公钥加密

    String encryptStr = rsa.encryptBase64("123456", KeyType.PublicKey);
    
  • 使用私钥解密

    String decryptStr = rsa.decryptStr(encryptStr, KeyType.PrivateKey);
    

4.3 hutool MD5加密

String md5Str = MD5.create().digestHex("123456")

完整的测试代码:

public static void main(String[] args) {
    // 初始化RSA类
    RSA rsa = new RSA();
    // 生成公钥、私钥
    String privateKeyBase64 = rsa.getPrivateKeyBase64();
    String publicKeyBase64 = rsa.getPublicKeyBase64();
    // 公钥加密
    String encryptStr = rsa.encryptBase64("123456", KeyType.PublicKey);
    System.out.println(encryptStr);
    // 私钥解密
    String decryptStr = rsa.decryptStr(encryptStr, KeyType.PrivateKey);
    System.out.println(decryptStr);
    // md5加密
    String md5Str = MD5.create().digestHex(decryptStr);
    System.out.println(md5Str);
}

五、注册接口升级 - 项目实战 手把手

5.1 Web层配置注入RSA

3-2. SpringBoot项目集成【用户身份认证】实战 【实战核心篇】基于JWT生成和校验Token

在【3-2】的第五段 已经定义了配置类,也在配置文件定义了rsa的公钥私钥配置,同理把RSA也注入进来!

7.14 注册登录如何安全传输密码?如何安全保存密码?SpringBoot实战项目手把手教你_第1张图片

5.2 Service层使用RSA+MD5

AuthServiceImpl中注入`RSA:

7.14 注册登录如何安全传输密码?如何安全保存密码?SpringBoot实战项目手把手教你_第2张图片

此时,我们接收到的是使用RSA公钥加密的密码,所以:

  • 对于注册:先RSA私钥解密,再做密码有效性校验,最后MD5加密保存到数据库
  • 对于登录:先RSA私钥解密,再MD5加密,与数据库保存的密码对比

基于此,我封装了这个方法(注释够清晰了吧?):

/**
 * 将用RSA公钥加密的密码,转为MD5加密的密码
 *
 **/
private String rsaToMd5(String password, boolean isRegister) {
    // 1. RSA私钥解密
    String decryptPwd;
    try {
        decryptPwd = rsa.decryptStr(password, KeyType.PrivateKey);
    } catch (Exception e) {
        log.error("rsaToMd5异常:{}", e.getMessage(), e);
        return null;
    }
    // 2. 如果是注册:密码有效性校验
    if (isRegister) {
        // 密码有效性校验,例如:8-16位字符,必须包含大、小写字母及数字
        // 这里实现你想定义的校验规则
    }
    // 3. MD5加密
    return MD5.create().digestHex(decryptPwd);
}

注册接口:

调rsaToMd5方法

用Assert做个密码校验

7.14 注册登录如何安全传输密码?如何安全保存密码?SpringBoot实战项目手把手教你_第3张图片

登录接口:

和注册类似,调rsaToMd5方法

用Assert做个密码校验

7.14 注册登录如何安全传输密码?如何安全保存密码?SpringBoot实战项目手把手教你_第4张图片

注意这里的Assert方法参数里多了个code,是新增的,这也是自定义Assert的好处,随心所欲:

/**
 * obj不能为空,如果是空则抛出异常
 **/
public static void notNull(Object obj, String code, String msg) {
    if (isNullOrBlank(obj)) {
        throw new BizException(code, msg);
    }
}

最后

当然了,加密算法你可以任意组合使用,比如:RSA+AES+MD5,或者AES+RSA+MD5等等还可以嵌套调用,无数种方案。。。

看到这,觉得有帮助的,刷波666,感谢大家的支持~

想要看更多实战好文章,还是给大家推荐我的实战专栏–>《基于SpringBoot+SpringCloud+Vue前后端分离项目实战》,由我和 前端狗哥 合力打造的一款专栏,可以让你从0到1快速拥有企业级规范的项目实战经验!

具体的优势、规划、技术选型都可以在《开篇》试读!

订阅专栏后可以添加我的微信,我会为每一位用户进行针对性指导!

另外,别忘了关注我:天罡gg ,怕你找不到我,发布新文不容易错过: https://blog.csdn.net/scm_2008

你可能感兴趣的:(spring,boot,后端,java,RSA,MD5,hutool,注册和登录)