需求分析:抢课开放时,大量用户同时访问抢课接口,防止有人利用程序恶意刷接口进行抢课。
1.导入验证码依赖
<!--验证码依赖-->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>1.6.2</version>
</dependency>
2.前端判断抢课时间是否开始,一旦开始用户点击某个课程进入抢课页面就向服务器发送请求,服务器j进行响应生成验证码结果:
<div class="row">
<div class="form-inline">
<img id="captchaImg" width="130" height="32" onclick="refreshCaptcha()"/>
<input id="captcha" class="form-control">
<button class="btn btn-primary btn-block" type="button" id ="buyButton" onclick="getSeckillPath()">立即秒杀
<input type="hidden" name="courseId" id ="courseId">
</button>
</div>
</div>
function refreshCaptcha() {
$("#captchaImg").attr("src", "/seckill/captcha?courseId=" + $("#courseId")
.val() + "&time=" + new Date());
}
/ @ApiOperation("获取验证码")
@GetMapping(value = "/captcha")
public void verifyCode(User tUser, Long goodsId, HttpServletResponse response) {
if (tUser == null || goodsId < 0) {
throw new GlobalException(RespBeanEnum.REQUEST_ILLEGAL);
}
//设置请求头为输出图片的类型
response.setContentType("image/jpg");
response.setHeader("Pargam", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
//生成验证码
ArithmeticCaptcha captcha = new ArithmeticCaptcha(130, 32, 3);
redisTemplate.opsForValue().set("captcha:" + tUser.getId() + ":" + goodsId, captcha.text(), 300, TimeUnit.SECONDS);
try {
captcha.out(response.getOutputStream());
} catch (IOException e) {
log.error("验证码生成失败", e.getMessage());
}
}
3.CourseOrderservice中编写验证码检验逻辑代码,使用的是数字验证码,用户输入结果后传入与Redis中预存的结果进行比较
//接口
boolean checkCaptcha(User tuser, Long goodsId, String captcha);
@Override
public boolean checkCaptcha(User user, Long goodsId, String captcha) {
if (user == null || goodsId < 0 || StringUtils.isEmpty(captcha)) {
return false;
}
String redisCaptcha = (String) redisTemplate.opsForValue().get("captcha:" + user.getId() + ":" + goodsId);
return captcha.equals(redisCaptcha);
}