7.14 How to securely transmit passwords during registration and login? How to store passwords securely? SpringBoot practical projects teach you step by step

CSDN achieves 100 million technical people


Preface

In the previous chapters, we implemented simple registration and login functions. For other functions, such as verification codes, current limiting, etc., you may be able to find solutions with a little research, but there is one point that may not be so easy for you to solve, and that is How to securely transmit registration login password?
One thing is certain: the password must be encrypted and must not be transmitted in clear text! But how to choose the encryption algorithm? How to store passwords safely?
If you don’t have some project experience, it may be a bit tricky and may feel less secure in the end. It’s not difficult for those who know it, but it’s not difficult for those who can!
Based on this, I decided to write a short blog post today to teach you step by step how to solve the problems of password transmission and password saving in SpringBoot practical projects!
Finally, after reading this article, you should also check whether your project can safely transmit passwords and whether it can safely store passwords!

The blog posts related to the registration and login interface mentioned before:

Login interface: 3-3. SpringBoot project integration [User Identity Authentication] Practical Combat [Full Process] Login + Logout + Interceptor based on JWT + double check

Registration interface: 5.4 How to use insert tag in Mybatis and return the primary key id? -- Teach you common practices


1. Review the simple registration and login issues

Let’s review the process we wrote before:

Registration:前端: MD5(password), 后端:stores the password passed in by the front end!

Login:前端: MD5(password), 后端:match the password passed in from the front end with the password saved in the database. If the match is successful, the login is successful!

看出来问题了吗?

If it is an internal system, deployed on the intranet , and everyone calls it legally, then everything should be fine!

But if it is deployed on the Internet , you may face the risk of malicious calls at any time . The backend neither verifies the validity of the password nor verifies the legality of the password . To put it bluntly, the backend has no control over the password. You don’t have any rights. If a hacker sends you a clear message of 123456, there’s nothing you can do about it!


2. What must be done

Recognizing the problem is half the solution!

  • First , the password filled in by the user during registration must not be directly transmitted to the backend in plain text. The frontend must encrypt it , and it must also support decryption by the backend, 为什么?
    because the backend needs to verify the validity of8-16位字符,必须包含大、小写字母及数字 the password, for example: !

  • Second , after the backend passes the validity check, it must save the password that cannot be decrypted . 为什么?
    If the password saved in the database can be decrypted, is it possible for developers, DBAs, hackers, etc. to see the user's password? Therefore, the safe approach is: the database stores undecryptable passwords!


3. Scheme design

  • For the first point , we can use encryption algorithms such as AES or RSA , which are relatively safe and can be decrypted. I recommend RSA because it is asymmetric encryption! Asymmetric means that the encryption and decryption keys are different!
    It is worth mentioning that the RSA encryption algorithm is highly secure and very trustworthy. The longer the number of digits, the safer it is. It is very difficult to crack without a secret key!
    In addition, since AES is symmetric encryption, the secret key for front-end encryption and back-end decryption is the same , so where to store the secret key is also a problem, and how to prevent the secret key from being leaked is also a problem! Because you can decrypt it with this unique key! ! ! With the RSA encryption algorithm, you are not afraid even if the public key is leaked, because RSA is asymmetric encryption, the public key is encrypted, and the private key can be decrypted! The private key is stored in the backend, so the security is higher!

  • Regarding the second point , save an undecryptable password, the well-known is MD5 . As long as your password is not too simple, it will be difficult to be cracked by brute force! All right~


4. Landing

4.1 Introduction of hutool tool package

I use the ready-made encryption method provided by hutooldependencyManagement.dependencies here, and first introduce the dependency in the parent project pom.xml:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.12</version>
</dependency>

Then introduce dependencies into the common subproject (no version number required)

4.2hutool RSA encryption and decryption

  • Initialize the RSA class

    RSA rsa = new RSA();
    
  • Generate public key and private key

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

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

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

4.3 hutool MD5 encryption

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

Complete test code:

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. Registration interface upgrade - practical project step-by-step

5.1 Web layer configuration injection RSA

3-2. SpringBoot project integration [User Identity Authentication] Practical Combat [Practical Core Chapter] Generate and verify Token based on JWT

In the fifth paragraph of [3-2], the configuration class has been defined and also defined in the configuration filersa的公钥私钥配置 . In the same way, RSA is also injected!

RSA injection

5.2 Service layer uses RSA+MD5

AuthServiceImplInject `RSA in :

Insert image description here

At this point, we receive RSA公钥the password using encryption, so:

  • For registration: first RSA私钥decrypt, then verify password validity, and finally save MD5 encryption to the database.
  • For login: first RSA私钥decrypt, then MD5 encryption, compare with the password saved in the database

Based on this, I encapsulated this method (are the comments clear enough?):

/**
 * 将用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);
}

Registration interface:

Call rsaToMd5 method

Use Assert to perform password verification

Insert image description here

Login interface:

Similar to registration, call the rsaToMd5 method

Use Assert to perform password verification

Insert image description here

Note that there is an extra code in the Assert method parameters here, which is new. This is also the benefit of customizing Assert. You can do whatever you want:

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

at last

Of course, you can use any combination of encryption algorithms, such as: RSA+AES+MD5, or AES+RSA+MD5, etc. You can also nest the calls, and there are countless solutions. . .

If you see this and find it helpful, please brush 666. Thank you for your support~

If you want to read more good practical articles, I would like to recommend my practical column –> "Practical Combination of Front-End and Front-End Separation Projects Based on SpringBoot+SpringCloud+Vue", a column jointly created by me and the front-end dog brother, which allows you to start from Quickly acquire enterprise-level standardized project practical experience from 0 to 1!

The specific advantages, planning, and technology selection can be read in the " Opening "!

After subscribing to the column, you can add my WeChat account and I will provide targeted guidance for each user!

In addition, don’t forget to follow me: Tiangang gg , in case you can’t find me, it’s not easy to miss new articles: https://blog.csdn.net/scm_2008

Guess you like

Origin blog.csdn.net/scm_2008/article/details/132922193