本章节主要描述短信15分钟内有效验证,过期则验证失败,以阿里云短信(java ssm)为例,如果不知道如何发送短信验证码的请看上一个章节。
本章节是大学时期写的,验证码失效功能请参考邮箱验证的第二章节
https://blog.csdn.net/qq_26751319/article/details/135958695
验证码发送
- 添加VerificationCode类
此类用于接收code验证码和手机号,因为业务需要,验证完验证码之后需要手机号进行业务操作,这里不做解释,根据自己需求而定
package com.rxys.util;
import java.util.Random;
import java.util.TimerTask;
import java.util.concurrent.Callable;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
//必须实现Runnable方法,后面会使用到ScheduledThreadPool线程池
public class VerificationCode implements Runnable {
public String code;
public String phone;
private char[] array = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
public VerificationCode(String phone){
this.phone=phone;
}
//获取验证码
public String getCode() {
setCode();
return this.code;
}
//创建6位数验证码交给成员变量code
public void setCode() {
StringBuffer stringBuffer = new StringBuffer();
int i = 0;
while (i < 6) {
stringBuffer.append(array[new Random().nextInt(10)]);
i++;
}
this.code = stringBuffer.toString();
}
//过期后将该实例验证码为空值
@Override
public void run() {
this.code = "";
}
@Override
public String toString() {
return "VerificationCode=[code="+code+",phone="+phone+"]";
}
}
- 发送验证码controller层
//ParamVo主要接受前端参数,主要有phoneNumber和sessionId
//因为项目原因特殊,sessionId需要前端发送,这里可以用session.getId()获取。不懂的可以留言。
@PostMapping("/getCode")
public JsonResult getCode(@RequestBody ParamVo paramVo) {
return new JsonResult (phoneService.getCode(paramVo.getPhoneNumbers(),paramVo.getSessionId()));
}
-
发送验证码service层
成员中变量加上ScheduledThreadPool和hashmap
//ScheduledThreadPool是用来进行延迟任务,这里调用他的schedule()进行短信过期,ScheduledThreadPool还有几种方法大家可以百度查阅作为扩展知识
private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(Integer.MAX_VALUE);
//创建map用于根据sessionId存储VerificationCode实例,
private HashMap<String,VerificationCode> map=new HashMap<>();
getCode业务逻辑
/*此代码抛出ServiceException被@ExceptionHandler做了异常处理,可以跟根据自己业务修改返回错误*/
@Override
public String getCode(String phoneNumbers,String sessionId) {
//判断手机号是否为空
if (phoneNumbers == null || phoneNumbers.equals("")) {
throw new ServiceException("手机号码为空");
}
//创建verificationCode对象,将手机号存入实例
VerificationCode verificationCode=new VerificationCode(phoneNumbers);
//将verificationCode存入成员变量map中,sessionId为key
map.put(sessionId,verificationCode);
//获取验证码
String code = verificationCode.getCode();
//SendSmsUtil为阿里云验证工具类,不了解的请看上一个章节
//此处返回发送验证码回调信息
String result = SendSmsUtil.sendMeg(phoneNumbers, code);
//15分钟后执行verificationCode的run方法,设置code为空值(调用verificationCode的run方法,TimeUnit.MINUTES表示以分钟计时,15分钟后执行)
scheduledExecutorService.schedule(verificationCode, 15, TimeUnit.MINUTES);
//打印回到信息
System.out.println(result);
//将回调信息用map接收,此处使用阿里的JSON类
Map<String, String> map = JSON.parseObject(result, Map.class);
String message = map.get("Message");
//如果message不等于OK,则抛出异常。message不等于Ok则为异常信息
if (!message.equals("OK")) {
throw new ServiceException(message);
}
return "验证码发送成功";
}
- 接口测试
此时调用接口,短信发送成功(已收到短信)
验证码有效期验证
- controller层
//因为项目原因特殊,sessionId需要前端发送,这里可以用session.getId()获取。不懂的可以留言。
@PostMapping("/judgeCode")
public JsonResult judgeCode(@RequestBody ParamVo paramVo) {
return new JsonResult (phoneService.judgeCode(paramVo.getCode(),paramVo.getSessionId()));
}
- service层
/*此代码抛出ServiceException被@ExceptionHandler做了异常处理,可以跟根据自己业务修改返回错误*/
@Override
public String judgeCode(String code, String sessionId) {
//获取map中的verificationCode实例,sessionId为key获取
VerificationCode verificationCode=map.get(sessionId);
//如果verificationCode为null则验证码已被移除或者没有发送手机验证
if(verificationCode==null){
throw new ServiceException("请获取验证码");
}
//如果verificationCode为空字符则验证码失效,说明该实例的run方法已被ScheduledThreadPool调用
if (verificationCode.code.equals("")) {
throw new ServiceException("验证码过期");
}
//如果verificationCode与传入的code值不相等,则抛出验证码错误异常
if (!verificationCode.code.equals(code)) {
throw new ServiceException("验证码错误");
}
//以上判断顺序不可修改
//获取map中的校验成功后移除map中verificationCode对象
map.remove(sessionId);
return "验证成功";
}
-
接口测试
失效测试
校验成功测试
未发送测试