I heard that wechat search “Java fish” will change strong oh!

This article is in Java Server, which contains my complete series of Java articles, can be read for study or interview

(1) Overview

In daily use of a variety of apps or websites, you will basically see the function of SMS verification code. There are many ways to achieve SMS verification code. Here is the implementation of SMS verification code based on SpringBoot and Redis. Source code at the end of the article

(2) Ideas

Simplify everything, SMS verification code implementation can not be the following points:

1. The backend randomly generates SMS verification codes and stores them on the server for a certain time (usually 5 minutes).

2. Send the SMS verification code to the user.

3. After the user enters the SMS verification code, the verification code is compared with the generated SMS verification code on the back end. If the verification code is the same, the verification succeeds.

Which in the server to save a certain time of this operation I suddenly thought of Redis, then use Redis to achieve it!

If you are not familiar with how to use Redis in SpringBoot, you can take a quick look at my previous article: Redis To Master series 10: SpringBoot integration redis and redis tool class writing

(iii) Construction projects

First, build a SpringBoot project, I won’t talk about this step, if you still have questions can directly look at my SpringBoot series.

3.1 Importing Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
Copy the code

All you need to do here is introduce the above three dependencies.

3.2 configuration Controller

Create a new package called Controller, create a new class IndexController, and write a simple home page jump:

@Controller
public class IndexController {
    @RequestMapping(value = {"/","/index"},method = RequestMethod.GET)
    public String index(a){
        return "index"; }}Copy the code

At this point, if you visit IP: port/or IP: port /index, you will be redirected to index.html.

3.3 write index. HTML

The page only needs to contain two buttons and an input box, and the page is placed under Resources/Templates

<! DOCTYPEhtml>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body>
<button type="button">Send verification code</button>
<input type="text" id="input_code"/>
<button type="button">validation</button>
</body>
</html>
Copy the code

Here is a simple preliminary construction of the project is completed, visit:

Realization of core functions

4.1 configure redis

Redis need to write a configuration class before the official use, I have written in the Redis series of blogs, here is directly used, create a package called config, new class RedisConfig, this class is mainly to make Redis in the transmission process will not be garbled.

@Configuration
public class RedisConfig {
    // A custom redistemplate
    @Bean(name = "redisTemplate")
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        // Create a RedisTemplate Object that returns key string and value Object for convenience
        RedisTemplate<String,Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        // Set the JSON serialization configuration
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new
                Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper=new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance);
        // Serialization of string
        StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
        // Key uses string serialization
        template.setKeySerializer(stringRedisSerializer);
        //value uses Jackson's serialization
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // Hashkey uses string serialization
        template.setHashKeySerializer(stringRedisSerializer);
        // HashValue uses Jackson's serialization
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        returntemplate; }}Copy the code

4.2 Implementation of the Sending Verification Code Function

The idea of sending the verification code is to generate the verification code, store the verification code, and send the verification code through the SMS interface. There are a lot of SMS interfaces on the market, and the use of them is nothing more than a GET or POST request. I’ll use console output instead.

Add an interface to the IndexController for sending SMS verification codes:

@Controller
public class IndexController {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @RequestMapping(value = {"/","/index"},method = RequestMethod.GET)
    public String index(a){
        return "index";
    }

    @ResponseBody
    @RequestMapping(value = "/sendmessage",method = RequestMethod.GET)
    public String sendmessage(a){
        // The userId is obtained from the token of the personal identity in the real business
        String userId="1";
        // Generate a random six-digit verification code
        String code=getCode();
        // Set the redis key, here set it to project name
        String redisKey="VERIFATIONCODE:CODE:"+userId;
        // Store the verification code in Redis and set the expiration time to 5 minutes
        redisTemplate.opsForValue().set(redisKey,code,300, TimeUnit.SECONDS);
        // Send SMS messages
        boolean isSuccess=send(code);
        if (isSuccess){
            return "success";
        }else {
            return "fail"; }}private boolean send(String code) {
        String msg="Verification code is:"+code+Verification code is valid for 5 minutes. Please verify it in time.;
        System.out.println(msg);
        return true;
    }
    
    // Generate a random six-digit verification code
    private static String getCode(a) {
        Random random = new Random();
        String result="";
        for (int i=0; i<6; i++) { result+=random.nextInt(10);
        }
        returnresult; }}Copy the code

Redis’ key ‘is the name of the project and the field used by redis’ user Id.

Then add a click event to the button that sends the captcha on the front page and invoke the interface via Ajax.

<! DOCTYPEhtml>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body>
<button type="button" th:onclick="sendmessage()">Send verification code</button>
<input type="text" id="input_code"/>
<button type="button">validation</button>
<script>
    sendmessage=() = >{
        var resultjson;
        $.ajax(
            {
                url: "http://localhost:8080/sendmessage".type: "GET".async:false.dataType:'text'.success: function (result) {
                    resultjson=result;
                },
                error: function ( status) {
                    console.log("error")}});if (resultjson=='success'){
            alert("SMS sent successfully");
        }else{
            alert("SMS sending failed. Please contact the administrator.")}}</script>
</body>
</html>
Copy the code

4.4 Verifying SMS Verification Codes

Add an additional interface to the IndexController for validation. The logic is to compare the existing values in Redis to the input values

@ResponseBody
@RequestMapping(value = "/checkCode",method = RequestMethod.GET)
public String checkCode(@RequestParam("inputCode") String inputCode){
    String userId="1";
    // Set the redis key, here set it to project name
    String redisKey="VERIFATIONCODE:CODE:"+userId;
    String realCode= (String) redisTemplate.opsForValue().get(redisKey);
    if(realCode! =null&&realCode.equals(inputCode)){
        return "success";
    }else {
        return "fail"; }}Copy the code

Once again, add a click event to the verification button. Add the checkCode method to the SendMessage method.

<button type="button" th:onclick="checkCode()"> verify </button> checkCode=() = >{
    var resultjson;
    var input_code=$("#input_code").val();
    $.ajax({
            url: "http://localhost:8080/checkCode".type: "GET".async:false.dataType:'text'.data: {inputCode:input_code},
            success: function (result) {
                resultjson=result;
            },
            error: function ( status) {
                console.log("error")}});if (resultjson=='success'){
        alert("Verification successful");
    }else{
        alert("Verification failed, verification code error")}}Copy the code

(V) Effect display

First click send verification code, the message is sent successfully on the page, and the verification code is received in the background:

Observe the data in Redis

First enter a wrong data

Enter the correct data again

Finally give the source code: project source