基於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中的資料
首先輸入一個錯誤的資料
再輸入一個正確的資料
最後給出原始碼:專案原始碼