1. 程式人生 > 其它 >基於SpringBoot和Redis實現簡訊驗證碼功能

基於SpringBoot和Redis實現簡訊驗證碼功能

技術標籤:《一起實戰吧!》系列javaredisspringspringboot專案

聽說微信搜尋《Java魚仔》會變更強哦!

本文收錄於JavaStarter ,裡面有我完整的Java系列文章,學習或面試都可以看看哦

(一)概述

在日常使用各種app或者登陸網站的時候,基本都會看到簡訊驗證碼這個功能,實現簡訊驗證碼的方式有很多,這裡給出基於SpringBoot和Redis的簡訊驗證碼實現方式。原始碼在文末

(二)思路

把一切都簡化,簡訊驗證碼的實現無法就是下面幾點:

1、後端隨機生成簡訊驗證碼,並在伺服器端儲存一定時間(一般是5分鐘)。

2、將簡訊驗證碼發給使用者。

3、使用者輸入簡訊驗證碼提交後,在後端與之前生成的簡訊驗證碼作比較,如果相同說明驗證成功,否則驗證失敗。

其中在伺服器端儲存一定時間的這個操作我一下子就想到了redis,那就用redis來實現吧!

如果你還不熟悉如何在SpringBoot中使用redis,可以快速翻閱一下我之前的一篇文章:
redis入門到精通系列(十):springboot整合redis及redis工具類的編寫

(三)搭建專案

首先搭建一個SpringBoot專案,這一步就不講了,如果你還有問題可以直接看我的SpringBoot系列。

3.1 引入依賴

<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>

這裡只需要引入上面三個依賴即可。

3.2 配置Controller

新建一個包叫Controller,新建類IndexController,編寫一個簡單的首頁跳轉:

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

此時,如果訪問ip:埠/或者ip:埠/index,就會跳轉到index.html這個頁面上去。

3.3 編寫index.html

這個頁面只需要包含兩個按鈕和一個輸入框即可,頁面放在resources/templates下

<!DOCTYPE html>
<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">傳送驗證碼</button>
<input type="text" id="input_code"/>
<button type="button">驗證</button>
</body>
</html>

到這裡一個簡單的專案前期搭建就完成了,訪問一下:
在這裡插入圖片描述

(四)核心功能實現

4.1 配置redis

redis在正式使用前需要編寫一個配置類,我在redis系列的部落格中都有寫,這裡就直接用了,新建一個包叫做config,新建類RedisConfig,這個類主要是讓redis在傳輸過程中不會亂碼。

@Configuration
public class RedisConfig {
    //自定義的redistemplate
    @Bean(name = "redisTemplate")
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        //建立一個RedisTemplate物件,為了方便返回key為string,value為Object
        RedisTemplate<String,Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        //設定json序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new
                Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper=new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance);
        //string的序列化
        StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
        //key採用string的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        //value採用jackson的序列化方式
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //hashkey採用string的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        //hashvalue採用jackson的序列化方式
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

4.2 傳送驗證碼功能的實現

傳送驗證碼的思路就是生成驗證碼,儲存驗證碼,通過簡訊介面傳送驗證碼。這裡的簡訊介面市面上有很多,使用起來無非就是一個get或者post請求,我這裡就用控制檯輸出代替了。

在IndexController增加一個介面,用於傳送簡訊驗證碼:

@Controller
public class IndexController {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

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

    @ResponseBody
    @RequestMapping(value = "/sendmessage",method = RequestMethod.GET)
    public String sendmessage(){
        //這裡的userId在真實業務中通過個人身份的令牌獲取,這裡直接仿造一個
        String userId="1";
        //生成六位數隨機驗證碼
        String code=getCode();
        //設定redis的key,這裡設定為專案名:使用的欄位:使用者Id
        String redisKey="VERIFATIONCODE:CODE:"+userId;
        //將這個驗證碼存入redis中,並設定失效時間為5分鐘
        redisTemplate.opsForValue().set(redisKey,code,300, TimeUnit.SECONDS);
        //傳送簡訊
        boolean isSuccess=send(code);
        if (isSuccess){
            return "success";
        }else {
            return "fail";
        }
    }

    private boolean send(String code) {
        String msg="驗證碼為:"+code+",驗證碼有效期5分鐘,請及時驗證";
        System.out.println(msg);
        return true;
    }
    
    //生成六位隨機驗證碼
    private static String getCode() {
        Random random = new Random();
        String result="";
        for (int i=0;i<6;i++)
        {
            result+=random.nextInt(10);
        }
        return result;
    }
}

程式碼註釋都寫了,需要注意的是redis的key值命名方式,將專案名:使用的欄位:使用者Id設定為key,當然也可以採用其他辦法。

接著在前端的頁面上給傳送驗證碼的按鈕增加一個點選事件,並通過ajax來呼叫介面。

<!DOCTYPE html>
<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()">傳送驗證碼</button>
<input type="text" id="input_code"/>
<button type="button">驗證</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("簡訊傳送成功");
        }else{
            alert("簡訊傳送失敗,請聯絡管理員處理")
        }
    }
</script>
</body>
</html>

4.4 驗證簡訊驗證碼

在IndexController中再增加一個介面用來驗證,邏輯就是把redis中存在的值和輸入值進行比較

@ResponseBody
@RequestMapping(value = "/checkCode",method = RequestMethod.GET)
public String checkCode(@RequestParam("inputCode") String inputCode){
    String userId="1";
    //設定redis的key,這裡設定為專案名:使用的欄位:使用者Id
    String redisKey="VERIFATIONCODE:CODE:"+userId;
    String realCode= (String) redisTemplate.opsForValue().get(redisKey);
    if (realCode!=null&&realCode.equals(inputCode)){
        return "success";
    }else {
        return "fail";
    }
}

還是一樣給驗證按鈕也加一個點選事件,checkCode方法加到sendmessage方法後。

<button type="button" th:onclick="checkCode()">驗證</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("驗證成功");
    }else{
        alert("驗證失敗,驗證碼錯誤")
    }
}

(五)效果展現

首先點擊發送驗證碼,頁面上彈出簡訊傳送成功,後臺接收到驗證碼:

在這裡插入圖片描述

觀察redis中的資料

在這裡插入圖片描述

首先輸入一個錯誤的資料

在這裡插入圖片描述

再輸入一個正確的資料
在這裡插入圖片描述

最後給出原始碼:專案原始碼