SpringBoot使用hutool-captcha实现验证码生成与验证

 更新时间:2023年12月04日 15:28:15   作者:相思比梦长  
在springboot的登陆页面中为了防止机器大规模注册,机器暴力破解数据密码等危害,需要验证随机生成的验证码,本文主要介绍了SpringBoot使用hutool-captcha实现验证码生成与验证,感兴趣的可以了解一下

生成验证码

提供一个接口, 这个接口里,我们将生成的验证码存入session,然后将验证码以图片格式或者base64编码串返回给调用端。

校验验证码

提供一个接口,这个接口里,我们收到调用端传过来的校验码,然后从session取出验证码,两个验证码都全部转小写,进行无大小写区分匹配校验,返回true/flase 。

1、pom文件中导入hutool-captcha依赖

<dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.7.12</version>
</dependency>

2、创建后端控制类生成验证码

创建控制类CommonController类,一方面通过流的方式将随机生成的验证码图片信息发送到前端浏览器;另一方面将验证码中的验证信息写入session中,以方便后续的验证。

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;

import cn.hutool.captcha.ShearCaptcha;
import VerifyCodeVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author author
 */
@RestController
@Api(tags = "验证码工具类")
public class CommonController {
    @Resource
    RedisTemplate<String, String> redisTemplate;

    /**
     * 方法一 ShearCaptcha
     * 图片格式
     * session存储
     * 接口需添加白名单放行
     *
     * @param request HttpServletRequest
     */
    @GetMapping("/verify")
    @ApiOperation("生成验证码")
    public void verify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("image/jpeg");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        //定义图形验证码的长、宽、验证码字符数、干扰线宽度
        ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(150, 40, 5, 4);
        //图形验证码写出,可以写出到文件,也可以写出到流
        shearCaptcha.write(response.getOutputStream());
        //获取验证码中的文字内容
        request.getSession().setAttribute("verifyCode", shearCaptcha.getCode());
    }

    /**
     * 方法二 LineCaptcha
     * 图片格式
     * session存储
     * 接口需添加白名单放行
     *
     * @param request HttpServletRequest
     */
    @GetMapping("/verifyTwo")
    @ApiOperation("生成验证码")
    public void verifyTwo(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("image/jpeg");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        //定义图形验证码的长、宽、验证码字符数、干扰线宽度
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(150, 40, 5, 4);
        //图形验证码写出,可以写出到文件,也可以写出到流
        ImageIO.write(lineCaptcha.getImage(), "JPEG", response.getOutputStream());
        //获取验证码中的文字内容
        request.getSession().setAttribute("verifyCode", lineCaptcha.getCode());
    }

    /**
     * 方法三 ShearCaptcha
     * 图片的base64编码字符串
     * session存储
     * 接口需添加白名单放行
     *
     * @param request HttpServletRequest
     * @return String
     */
    @GetMapping("/getVerify")
    @ApiOperation("生成验证码")
    public String getVerify(HttpServletRequest request) {
        //定义图形验证码的长、宽、验证码字符数、干扰线宽度
        ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(150, 40, 5, 4);
        //获取验证码中的文字内容
        request.getSession().setAttribute("verifyCode", shearCaptcha.getCode());
        String base64String = "";
        try {
            base64String = "data:image/png;base64," + shearCaptcha.getImageBase64();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return base64String;
    }

    /**
     * 方法四 LineCaptcha
     * 图片的base64编码字符串
     * session存储
     * 接口需添加白名单放行
     *
     * @param request HttpServletRequest
     * @return String
     */
    @GetMapping("/getVerifyTwo")
    @ApiOperation("生成验证码")
    public String getVerifyTwo(HttpServletRequest request) {
        //定义图形验证码的长、宽、验证码字符数、干扰线宽度
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(150, 40, 5, 4);
        //获取验证码中的文字内容
        request.getSession().setAttribute("verifyCode", lineCaptcha.getCode());
        String base64String = "";
        try {
            //返回 base64
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ImageIO.write(lineCaptcha.getImage(), "JPEG", bos);
            byte[] bytes = bos.toByteArray();
            Base64.Encoder encoder = Base64.getEncoder();
            base64String = "data:image/png;base64," + encoder.encodeToString(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return base64String;
    }

    /**
     * 方法五 ShearCaptcha
     * 图片的base64编码字符串
     * redis存储
     * 接口需添加白名单放行
     *
     * @return String
     */
    @GetMapping("/getVerifyThree")
    @ApiOperation("生成验证码")
    public VerifyCodeVO getVerifyThree() {
        String captchaKey = UUID.randomUUID().toString();
        //定义图形验证码的长、宽、验证码字符数、干扰线宽度
        ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(150, 40, 5, 0);
        // 存入redis并设置过期时间为30分钟
        redisTemplate.opsForValue().set("captcha:" + captchaKey, shearCaptcha.getCode(), 30L, TimeUnit.MINUTES);
        //captcha:d6e561a6-7929-4469-8154-008710932f61
        String base64String = "";
        try {
            base64String = "data:image/png;base64," + shearCaptcha.getImageBase64();
        } catch (Exception e) {
            e.printStackTrace();
        }
        VerifyCodeVO verifyCodeVO = new VerifyCodeVO();
        verifyCodeVO.setCaptchaKey(captchaKey);
        verifyCodeVO.setCaptchaImg(base64String);
        return verifyCodeVO;
    }

    /**
     * 方法六 LineCaptcha
     * 图片的base64编码字符串
     * redis存储
     * 接口需添加白名单放行
     *
     * @return String
     */
    @GetMapping("/getVerifyFour")
    @ApiOperation("生成验证码")
    public VerifyCodeVO getVerifyFour() {
        String captchaKey = UUID.randomUUID().toString();
        //定义图形验证码的长、宽、验证码字符数、干扰线宽度
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(150, 40, 5, 4);
        // 存入redis并设置过期时间为30分钟
        redisTemplate.opsForValue().set("captcha:" + captchaKey, lineCaptcha.getCode(), 30L, TimeUnit.MINUTES);
        //captcha:d6e561a6-7929-4469-8154-008710932f61
        String base64String = "";
        try {
            //返回 base64
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ImageIO.write(lineCaptcha.getImage(), "JPEG", bos);
            byte[] bytes = bos.toByteArray();
            Base64.Encoder encoder = Base64.getEncoder();
            base64String = "data:image/png;base64," + encoder.encodeToString(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        VerifyCodeVO verifyCodeVO = new VerifyCodeVO();
        verifyCodeVO.setCaptchaKey(captchaKey);
        verifyCodeVO.setCaptchaImg(base64String);
        return verifyCodeVO;
    }
}

3、实现验证码的验证与返回结果

对前端输入的数据并发送到服务器的验证信息进行校验,当输入信息与验证码信息一致则返回true,否则返回false。

     /**
     * session存储
     *
     * @param captchaCode 验证码
     * @param request     HttpServletRequest
     * @return boolean
     */
    @GetMapping("/checkCaptcha")
    @ApiOperation("验证码校验")
    public boolean getCheckCaptcha(@RequestParam("captchaCode") String captchaCode, HttpServletRequest request) {
        try {
            // toLowerCase() 不区分大小写进行验证码校验
            String sessionCode = String.valueOf(request.getSession().getAttribute("verifyCode")).toLowerCase();
            System.out.println("session里的验证码:" + sessionCode);
            String receivedCode = captchaCode.toLowerCase();
            System.out.println("用户的验证码:" + receivedCode);
            return !"".equals(sessionCode) && !"".equals(receivedCode) && sessionCode.equals(receivedCode);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * redis存储
     *
     * @param captchaCode 验证码
     * @param request     HttpServletRequest
     * @return boolean
     */
    @GetMapping("/checkCaptchaTwo")
    @ApiOperation("验证码校验")
    @ApiImplicitParam(value = "Captcha-Key", name = "Captcha-Key", paramType = "header", dataType = "String", required = true)
    public boolean getCheckCaptchaTwo(@RequestParam("captchaCode") String captchaCode, HttpServletRequest request) {
        try {
            // toLowerCase() 不区分大小写进行验证码校验
            String redisCode = String.valueOf(redisTemplate.opsForValue().get("captcha:" + request.getHeader("Captcha-Key"))).toLowerCase();
            System.out.println("redisCode里的验证码:" + redisCode);
            String receivedCode = captchaCode.toLowerCase();
            System.out.println("用户的验证码:" + receivedCode);
            return !"".equals(redisCode) && !"".equals(receivedCode) && redisCode.equals(receivedCode);
        } catch (Exception e) {
            return false;
        }
    }

 Redis存储,返回工具类:

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;

@Data
public class VerifyCodeVO implements Serializable {
    @ApiModelProperty(value = "header头参数:Captcha-Key")
    private String captchaKey;
    @ApiModelProperty(value = "验证码图片")
    private String captchaImg;
}

启动应用,访问 http://localhost:8080/verify 即可得到验证码,如图: 

 前端调用展示:在img标签中src属性调用 /verify 接口,将传过来的图片验证码显示即可。若想换一张显示(刷新验证码):在img标签中增加一个onclick属性点击事件即可。

    <img src="/verify" id="verifyCode" onclick="refresh()" alt="验证码" />
    <script>
        /* 刷新验证码 */
        function refresh() {
            document.getElementById("verifyCode").src = "verify?time=" + new Date().getTime();
        }
    </script>

到此这篇关于SpringBoot使用hutool-captcha实现验证码生成与验证的文章就介绍到这了,更多相关SpringBoot验证码生成与验证内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • web.xml SpringBoot打包可执行Jar运行SpringMVC加载流程

    web.xml SpringBoot打包可执行Jar运行SpringMVC加载流程

    这篇文章主要为大家介绍了web.xml SpringBoot打包可执行Jar运行SpringMVC加载流程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • List集合按某个属性或者字段进行分组的操作

    List集合按某个属性或者字段进行分组的操作

    这篇文章主要介绍了List集合按某个属性或者字段进行分组的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • SpringBoot浅析Redis访问操作使用

    SpringBoot浅析Redis访问操作使用

    Redis是一个速度非常快的非关系数据库(Non-Relational Database),它可以存储键(Key)与多种不同类型的值(Value)之间的映射(Mapping),可以将存储在内存的键值对数据持久化到硬盘,可以使用复制特性来扩展读性能,还可以使用客户端分片来扩展写性能
    2022-11-11
  • Java 中实现异步的多种方式

    Java 中实现异步的多种方式

    文章介绍了Java中实现异步处理的几种常见方式,每种方式都有其特点和适用场景,通过选择合适的异步处理方式,可以提高程序的性能和可维护性,感兴趣的朋友一起看看吧
    2025-03-03
  • bootstrap.yml如何读取nacos配置中心的配置文件

    bootstrap.yml如何读取nacos配置中心的配置文件

    这篇文章主要介绍了bootstrap.yml读取nacos配置中心的配置文件问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • Spring boot 整合CXF开发web service示例

    Spring boot 整合CXF开发web service示例

    这篇文章主要介绍了Spring boot 整合CXF开发web service示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 使用JAR包中MANIFEST.MF的注意事项

    使用JAR包中MANIFEST.MF的注意事项

    这篇文章主要介绍了使用JAR包中MANIFEST.MF的注意事项,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • MyBatis中操作类对象的实现

    MyBatis中操作类对象的实现

    在MyBatis框架中,操作类对象是用于执行数据库操作的核心对象,本文主要介绍了MyBatis中操作类对象的实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • 一文教你如何使用Java灵活读取Excel内容

    一文教你如何使用Java灵活读取Excel内容

    这篇文章主要给大家介绍了关于如何使用Java灵活读取Excel内容的相关资料,读取Excel数据是Java开发中常见的任务,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-09-09
  • 关于SpringBoot简介、官网构建、快速启动的问题

    关于SpringBoot简介、官网构建、快速启动的问题

    SpringBoot 是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程,这篇文章主要介绍了SpringBoot简介、官网构建、快速启动,需要的朋友可以参考下
    2022-07-07

最新评论