一、前言
今天在实现登录功能时,突然想到大部分网站都会设置的一个验证码功能,引入可以用于拦截机器非法攻击等情况,于是我立即就去查阅相关资料,最后决定使用easy-captcha工具包提供的验证码来实现验证码验证功能。
easy-captcha是一款国人开发的验证码工具,支持GIF、中文、算术等类型,可用于Java Web等项目,生成的验证码形式如下图所示。
由于我没有太高的要求,就挑了最简单的字母+数字的普通类型验证码来实现。在一番捣鼓后,解决了一些小问题,算是很简单地就实现了,下面我就简单讲一下实现步骤。
二、实现
(一)添加easy-captcha依赖
添加该依赖的方式有多种,推荐去maven依赖库官网搜索easy-captcha,以添加maven依赖的形式添加。据2022/8/5,也就是我写到这里的目前为止,我只看见了一个版本,大家也可以直接复制下面的代码去pom.xml文件里,黏贴后同时点击ctrl+shift+o进行添加。
<!-- 验证码 -->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>1.6.2</version>
</dependency>
(二)后端控制层生成验证码图并储存验证码,前端视图层进行请求获取
后端控制层代码如下:
package com.example.malldemo.controller.common;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
@RequestMapping("/common")
public class commonCotroller {
@GetMapping("/kaptcha")
public void defaultKaptcha(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
httpServletResponse.setHeader("Cache-Control", "no-store");
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.setContentType("image/gif");
// 三个参数分别为宽、高、位数
SpecCaptcha captcha = new SpecCaptcha(150, 30, 4);
// 设置字体
captcha.setCharType(Captcha.FONT_9);
// 验证码存入session
httpServletRequest.getSession().setAttribute("verifyCode", captcha.text().toLowerCase());
// 输出图片流
captcha.out(httpServletResponse.getOutputStream());
}
}
前端thymeleaf视图层代码如下:
<div class="row">
<div class="col-6">
<input type="text" class="form-control" name="verifyCode" placeholder="请输入验证码" required="true">
</div>
<div class="col-6">
<img alt="点击图片刷新!" src="/common/kaptcha" onclick="this.src='/common/kaptcha?d='+new Date()*1">
</div>
</div>
这里访问后端验证码路径/common/kaptcha,由于验证码是图片形式,所以将其显示在img标签中。然后定义onclick方法,在点击该img标签时可以动态切换显示一个新的验证码。点击时访问的路径为’/common/kaptcha?d='+new Date()*1,即原来的验证码路径后面带上一个时间戳参数 d。时间戳是会变化的,所以每次点击都会是一个与之前不同的请求。
(三)表单提交后,登录时的验证实现
//如果表单提交填入的验证码为空
if (StringUtils.isEmpty(verifyCode)) {
session.setAttribute("errorMsg", "验证码不能为空");
//...下面表单提交填入的验证码为空后的动作
}
String kaptchaCode = session.getAttribute("verifyCode") + "";
//如果验证码错误
if (StringUtils.isEmpty(kaptchaCode) || !(verifyCode.toLowerCase()).equals(kaptchaCode)) {
session.setAttribute("errorMsg", "验证码错误");
//...下面写验证码错误后的动作
}
//...若填入提交的验证码既不为空也不错误,可以写接下来的验证或登录事件了
三、最后
本篇文章讲的是传统输入式验证码在SpringBoot过程中的引入实现,经过以上三步基本是可以实现的了。在实现过程中,我也遇到了许多问题,比如图片中某个字母明明是大写的,生成的验证码中那个字母却是小写的,所以也导致了屡验屡错。思考过后,我以toLowerCase()将生成存入session的验证码转变为小写的,并且在登录表单提交后验证时,也以toLowerCase()将填入提交的验证码转为小写,这样就可以以小写匹配小写,规避了原本easy-captcha工具包在大小写问题上出错的可能。
如果大家有什么问题,也欢迎提出哈,一起讨论一起解决。