# 目标 - 完成一个手机验证码功能
要求:
1、输入手机号,点击发送后随机生成 6 位数字码,2 分钟有效
2、输入验证码,点击验证,返回成功或失败
3、每个手机号每天只能输入 3 次
实现:
# 前端代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" | |
pageEncoding="UTF-8"%> | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Insert title here</title> | |
<script src="static/jquery/jquery-3.1.0.js" ></script> | |
<link href="static/bs/css/bootstrap.min.css" rel="stylesheet" /> | |
<script src="static/bs/js/bootstrap.min.js" ></script> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="row"> | |
<div id="alertdiv" class="col-md-12"> | |
<form class="navbar-form navbar-left" role="search" id="codeform"> | |
<div class="form-group"> | |
<input type="text" class="form-control" placeholder="填写手机号" name="phone_no"> | |
<button type="button" class="btn btn-default" id="sendCode">发送验证码</button><br> | |
<font id="countdown" color="red" ></font> | |
<br> | |
<input type="text" class="form-control" placeholder="填写验证码" name="verify_code"> | |
<button type="button" class="btn btn-default" id="verifyCode">确定</button> | |
<font id="result" color="green" ></font><font id="error" color="red" ></font> | |
</div> | |
</form> | |
</div> | |
</div> | |
</div> | |
</body> | |
<script type="text/javascript"> | |
var t=120;// 设定倒计时的时间 | |
var interval; | |
function refer(){ | |
$("#countdown").text("请于"+t+"秒内填写验证码 "); // 显示倒计时 | |
t--; // 计数器递减 | |
if(t<=0){ | |
clearInterval(interval); | |
$("#countdown").text("验证码已失效,请重新发送! "); | |
} | |
} | |
$(function(){ | |
$("#sendCode").click( function () { | |
$.post("SendCodeServlet",$("#codeform").serialize(),function(data){ | |
if(data=="true"){ | |
t=120; | |
clearInterval(interval); | |
interval= setInterval("refer()",1000);// 启动 1 秒定时 | |
}else if (data=="limit"){ | |
clearInterval(interval); | |
$("#countdown").text("单日发送超过次数! ") | |
} | |
}); | |
}); | |
$("#verifyCode").click( function () { | |
$.post("CheckCodeServlet",$("#codeform").serialize(),function(data){ | |
if(data=="true"){ | |
$("#result").attr("color","green"); | |
$("#result").text("验证成功"); | |
clearInterval(interval); | |
$("#countdown").text("") | |
}else{ | |
$("#result").attr("color","red"); | |
$("#result").text("验证失败"); | |
} | |
}); | |
}); | |
}); | |
</script> | |
</html> |
# 后端代码:
- 点击发送验证码时:
将数据存入 redis 中
package com.dabing.redis.servlet; | |
import redis.clients.jedis.Jedis; | |
import javax.servlet.ServletException; | |
import javax.servlet.annotation.WebServlet; | |
import javax.servlet.http.HttpServlet; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import java.io.IOException; | |
import java.time.Duration; | |
import java.time.LocalTime; | |
import java.util.Random; | |
// 处理发送验证码的 Servlet | |
@WebServlet("/SendCodeServlet") | |
public class SendCodeServlet extends HttpServlet { | |
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | |
String phoneNo = request.getParameter("phone_no"); | |
if(phoneNo==null || "".equals(phoneNo)){ | |
return; | |
} | |
Jedis jedis = new Jedis("xxx.xxx.xx.xx",6379); | |
String countKey=phoneNo+":count"; // 生成验证码的次数 key | |
String codeKey=phoneNo+":code"; // 手机验证码 key | |
String count = jedis.get(countKey); | |
String code=getCode(6); | |
System.out.println("code="+code); | |
if(count==null){ | |
// 证明没有发送过验证码 | |
// 保存验证码到 redis,过期时间 120 秒 | |
jedis.setex(codeKey,120,code); | |
// 设置过期时间为今天的剩余时间 | |
jedis.setex(countKey,(int)getTheLeftSeconds(),"1"); | |
response.getWriter().write("true"); | |
}else if ("3".equals(count)){ | |
// 证明已经发送过 3 次了 | |
response.getWriter().write("limit"); | |
return;// 返回不让发了 | |
}else { | |
// 证明已经发过,但是次数没达到 3 次 | |
jedis.setex(codeKey,120,code); | |
jedis.incr(countKey);// 次数加 1 | |
response.getWriter().write("true"); | |
} | |
jedis.close(); | |
} | |
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | |
doPost(request,response); | |
} | |
// 随机生成验证码的方法 | |
private String getCode(int len) { | |
String code = ""; | |
for (int i = 0; i < len; i++) { | |
int rand = new Random().nextInt(10); | |
code += rand; | |
} | |
return code; | |
} | |
// 获取当天剩余秒数的方法 | |
private long getTheLeftSeconds(){ | |
// 获取现在的时间 | |
LocalTime now = LocalTime.now(); | |
// 获取当日 23 点 59 分 59 秒的时间 | |
LocalTime end = LocalTime.of(23, 59, 59); | |
// 获取 end 与 now 相差的秒数 | |
long millis = Duration.between(now, end).toMillis()/1000; | |
return millis; | |
} | |
} |
- 输入验证码校验时
从 redis 中取出对比
package com.dabing.redis.servlet; | |
import redis.clients.jedis.Jedis; | |
import javax.servlet.ServletException; | |
import javax.servlet.annotation.WebServlet; | |
import javax.servlet.http.HttpServlet; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import java.io.IOException; | |
// 处理验证验证码请求的 Servlet | |
@WebServlet("/CheckCodeServlet") | |
public class CheckCodeServlet extends HttpServlet { | |
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | |
String code=request.getParameter("verify_code"); | |
String phoneNo=request.getParameter("phone_no"); | |
if(code==null||phoneNo==null||"".equals(code)|| "".equals(phoneNo)){ | |
return; | |
} | |
Jedis jedis = new Jedis("xxx.xx.xxx.xx",6379); | |
String codeKey=phoneNo + ":code"; | |
String codeRedis = jedis.get(codeKey); | |
if(code.equals(codeRedis)){ | |
jedis.del(codeKey); | |
response.getWriter().write("true"); | |
} | |
jedis.close(); | |
} | |
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | |
doPost(request,response); | |
} | |
} |