一、前言

今天在实现登录功能时,突然想到大部分网站都会设置的一个验证码功能,引入可以用于拦截机器非法攻击等情况,于是我立即就去查阅相关资料,最后决定使用easy-captcha工具包提供的验证码来实现验证码验证功能。

easy-captcha是一款国人开发的验证码工具,支持GIF、中文、算术等类型,可用于Java Web等项目,生成的验证码形式如下图所示。

spring boot 验证码地址配置 springboot验证码登录_spring boot 验证码地址配置

由于我没有太高的要求,就挑了最简单的字母+数字的普通类型验证码来实现。在一番捣鼓后,解决了一些小问题,算是很简单地就实现了,下面我就简单讲一下实现步骤。

二、实现

(一)添加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工具包在大小写问题上出错的可能。

如果大家有什么问题,也欢迎提出哈,一起讨论一起解决。