基于SpringBoot和Hutool工具包实现的验证码案例

目录

验证码案例

1. 需求

2. 准备工作

3. 约定前后端交互接口 

需求分析

接口定义

4. Hutool 工具介绍

5. 实现验证码

后端代码 

前端代码

6. 运行测试 


验证码案例

随着安全性的要求越来越高,目前项目中很多都会使用验证码,只要涉及到登录,绝大多数都会有验证的要求,验证码的形式也是多种多样,更复杂的图形验证码和行为验证码已经成为了更流行的趋势。

验证码的实现方式很多,可以前端实现,也可以后端实现。网上也有比较多的插件或者工具包可以使用,这里选择使用 Hutool工具包 来实现一个简单的验证码案例。完整代码见文章末尾。

1. 需求

最终实现的验证码界面如下图所示:

1. 页面生成验证码

2. 输入验证码,点击提交,验证用户输入验证码是否正确且是否超时,正确且未超时则进行页面跳转,错误或已超时则进行提示,并更换验证码

2. 准备工作

创建SpringBoot项目,引入Spring-Web-MVC和Lombok的依赖包,前端界面会在后面提供.

3. 约定前后端交互接口 

需求分析

后端需要提供两个服务:

  1. 生成验证码,并返回验证码.
  2. 校验验证码是否正确.

接口定义

1)生成验证码

请求: 

请求URL:/captcha/get

 响应:浏览器显示图片内容

浏览器给服务器发送一个 /captcha/get 请求,服务器返回一个图片,浏览器显示在页面上

2)校验验证码是否正确

请求:

请求URL:/captcha/check
请求参数:captcha=验证码字符串

响应:

true or false
根据用户输入的验证码,校验验证码是否正确,并判断验证码是否超时

4. Hutool 工具介绍

Hutool官网:https://hutool.cn/

Hutool参考文档:https://hutool.cn/docs/#/

要使用Hutool工具包,需要在pom.xml文件中添加对应的依赖,参考文档中有详细介绍:

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

在Hutolol参考文档中找到图形验证码部分:

接下来可以就可以参考Hutool工具提供的方法,快速生成验证码,里面的介绍非常清晰,很容易看懂。此处使用如下格式验证码:

5. 实现验证码

项目目录结构如下:

后端代码 

实现接口

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hxxy.captchademo.config.CaptchaProperties;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.Date;

@RestController
@RequestMapping("/captcha")
public class CaptchaController {

    @Autowired
    private CaptchaProperties captchaProp;

    @RequestMapping("/get")
    public void getCaptcha(HttpServletResponse response, HttpSession session) {
        //定义图形验证码的长和宽(配置默认值)
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(captchaProp.getWidth(), captchaProp.getHeight());
        //细节问题,不影响程序
        //设置返回类型
        response.setContentType("image/jpeg");
        //静止缓存
        response.setHeader("Progma", "No-cache");
        try {
            //图形验证码写出,可以写出到文件,也可以写出到流
            lineCaptcha.write(response.getOutputStream());
            //同时将验证码内容和当前时间戳存储到Session中
            //此处Session的键可以配置成常量
            session.setAttribute(captchaProp.getSession().getKey(), lineCaptcha.getCode());
            session.setAttribute(captchaProp.getSession().getDate(), new Date());
            //关流
            response.getOutputStream().close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //验证码生效时间限制
    private static final long VALID_MILLIS_TIME = 60 * 1000;

    @RequestMapping("/check")
    public boolean checkCaptcha(String captcha, HttpSession session) {
        //保证传过来的参数是合法的
        if (StringUtils.hasLength(captcha)) {
            //根据配置的默认session信息获取key和date
            String key = (String) session.getAttribute(captchaProp.getSession().getKey());
            Date date = (Date) session.getAttribute(captchaProp.getSession().getDate());
            //1.验证码正确(不区分大小写)  2.验证码还未失效
            return key.equalsIgnoreCase(captcha)
                    && System.currentTimeMillis() - date.getTime() < VALID_MILLIS_TIME;
        }
        return false;
    }
}

代码解析:

  1. 通过@Autowired注解注入了一个CaptchaProperties对象,这个对象是用来配置图形验证码的属性的。使用这种方式是因为代码中的有些属性可能会在别处使用,且它们都是固定的,例如图形验证码的长和宽,Session的字段名等。将这些属性封装在一个对象中,并通过读取配置文件的方式绑定属性值。

  2. 在@RequestMapping注解的getCaptcha方法中,使用Hutool包的CaptchaUtil.createLineCaptcha方法创建了一个图形验证码对象lineCaptcha,其大小由配置文件中的captchaProp.getWidth()和captchaProp.getHeight()决定。然后,将验证码内容和当前时间戳存储到HttpSession中,以便后续校验验证码的时候使用。最后,将图形验证码写出到HttpServletResponse的输出流中,以返回给前端页面显示。

  3. 在@RequestMapping注解的checkCaptcha方法中,首先判断传入的验证码参数是否合法。如果合法,则从HttpSession中获取存储的验证码内容和时间戳信息,并进行比较。如果验证码正确且未过期,则返回true,否则返回false。

CaptchaProperties类的实现和配置文件(.yml)信息如下:

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
@ConfigurationProperties(prefix = "captcha")
public class CaptchaProperties {
    private Integer width;
    private Integer height;
    private Session session; //使用自定义的Session类

    @Data
    public static class Session {
        private String key;
        private String date;
    }
}
spring:
  application:
    name:
      captcha-demo

captcha:
  width: 200
  height: 100
  session:
    key: CAPTCHA_SESSION_KEY
    date: CAPTCHA_SESSION_DATE

此处还没有前端代码,但是已经可以先测试了,通常写好一个接口就可以测试一下。

启动项目,再访问 http://127.0.0.1:8080/captcha/get  显示验证码图片如下:

通过 Fiddler 进行抓包,HTTP请求和响应数据如下,图片就在响应的body部分:

前端代码

注意前端代码要放在resources的static目录下

index.html(重点关注script标签内的代码):

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">

    <title>验证码</title>
    <style>
        #inputCaptcha {
            height: 30px;
            vertical-align: middle;
        }

        #verificationCodeImg {
            vertical-align: middle;
        }

        #checkCaptcha {
            height: 40px;
            width: 100px;
        }
    </style>
</head>

<body>
<h1>输入验证码</h1>
<div id="confirm">
    <input type="text" name="inputCaptcha" id="inputCaptcha">
    <img id="verificationCodeImg" src="/captcha/get" style="cursor: pointer;" title="看不清?换一张"/>
    <input type="button" value="提交" id="checkCaptcha">
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
    //点击图片,切换验证码
    $("#verificationCodeImg").click(function () {
        //$(this).hide().attr('src', '/captcha/get?dt=' + new Date().getTime()).fadeIn();
        //使用attr()方法修改src属性值,获取一个新的验证码图片,后面添加一个时间戳参数来保证每次请求的验证码图片都是不同的
        $(this).attr('src', '/captcha/get?dt=' + new Date().getTime());
    });
    //点击提交按钮,进行验证码校验
    $("#checkCaptcha").click(function () {
        $.ajax({
            url: "/captcha/check",
            type: "post",
            data: {
                captcha: $("#inputCaptcha").val()
            },
            success: function (result) {
                if (result) {
                    location.href = "success.html";
                } else {
                    alert("验证码错误或已超时");
                    //验证码错误,重新生成验证码
                    $("#verificationCodeImg").attr('src', '/captcha/get?dt=' + new Date().getTime());
                    $("#inputCaptcha").val("");
                }
            }
        });
    });

</script>
</body>

</html>

JavaScript代码中主要包含两部分逻辑:

  1. 点击图片,切换验证码: 当id为"verificationCodeImg"的图片被点击时,会触发click事件的回调函数。回调函数通过修改图片的src属性,向后端发送一个请求来获取新的验证码图片,并使用当前时间戳作为参数,以确保每次请求的验证码图片都是不同的。最后,将获取到的新图片显示出来。

  2. 点击提交按钮,进行验证码校验: 当id为"checkCaptcha"的按钮被点击时,会触发click事件的回调函数。回调函数通过使用jQuery的ajax方法发送一个POST请求到"/captcha/check"接口,并传递了一个名为"captcha"的参数,该参数的值为id为"inputCaptcha"的输入框中用户输入的验证码。

    在请求成功后的回调函数中,会根据后端返回的结果(result)进行处理。如果校验成功,则跳转到"success.html"页面;如果校验失败,则弹出一个提示框显示"验证码错误或已超时",并重新生成新的验证码图片并清空输入框中的验证码。

success.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>验证成功页</title>
</head>
<body>
    <h1>验证成功</h1>
</body>
</html>

6. 运行测试 

启动项目,浏览器访问 http://127.0.0.1:8080/index.html 或 http://localhost:8080/index.html

输入错误的验证码: 

提示正确,且验证码能正确刷新,超时同样会提示以上错误。且点击验证码图片时,会重新生成验证码。

输入正确的验证码:

验证成功,页面正确跳转,测试完成。

完整代码:https://gitee.com/lv-jiacong/Java-EE/tree/master/captcha-demo/src

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/638144.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一个用Java编写的屏幕测距工具,包括游戏地图测量功能

该程序提供了一个简单便捷的方式&#xff0c;在屏幕上测量距离&#xff0c;包括游戏地图分析在内。它允许用户准确确定屏幕上两点之间的距离&#xff0c;帮助游戏过程中的战略规划、资源管理和决策制定。 特点&#xff1a; 简单易用的界面&#xff1a;直观的控制使测量距离变得…

Marin说PCB之POC电路layout设计仿真案例---03

今天天中午午休的时候&#xff0c;我刚要打开手机的准备刷抖音看无忧传媒的学生们的“学习资料”的时候&#xff0c;看到CSDN -APP上有提醒&#xff0c;一看原来是一位道友发的一个问题&#xff1a; 本来小编最近由于刚刚从国外回来&#xff0c;手上的项目都已经结束了&#xf…

MQTT到串口的转发(node.js)

本文针对以下应用场景&#xff1a;已有通过串口通信的设备或软件&#xff0c;想要实现跨网的远程控制。 node.js安装 从 Node.js — Run JavaScript Everywhere下载LTS版本安装包&#xff0c;运行安装程序。&#xff08;傻瓜安装&#xff0c;按提示点击即可&#xff09; 设置环…

忍の摸头之术游戏娱乐源码

本资源提供给大家学习及参考研究借鉴美工之用&#xff0c;请勿用于商业和非法用途&#xff0c;无任何技术支持&#xff01; 忍の摸头之术游戏娱乐源码&#xff0c;抖音上面非常火的摸头杀画面,看得我眼花缭乱,源码拿去玩吧&#xff1b; 目录说明 忍の摸头之术&#xff1a;域…

idea新建项目/模块找不到Spring Initializr

idea创建项目找不到spring intellij&#xff0c;如下图解决 可能是没有下载spring的相应插件&#xff0c;或者没有启用对应的插件 我这里就是没有启用插件&#xff0c;导致的创建项目时找不到按件。 全部启用后&#xff0c;重启idea即可。 重启后可以看到出现了“Spring Initi…

【Andoird开发】android获取蓝牙权限,beacon,android-beacon-library

iBeacon 最先是苹果的技术&#xff0c;使用android-beacon-library包可以在android上开发iBeacon 技术。 iBeacon的发明意义重大。它是一种基于蓝牙低功耗&#xff08;Bluetooth Low Energy, BLE&#xff09;技术的定位系统&#xff0c;通过向周围发送信号来标识其位置。这项技…

Docker 容器间通讯

1、虚拟ip/访问 同一网络 安装docker时&#xff0c;docker会默认创建一个内部的桥接网络docker0&#xff0c;每创建一个容器分配一个虚拟网卡&#xff0c;容器之间(包括宿主机)可以根据分配的ip互相访问(ps:其他主机(包括其他主机的容器)无法ping通docker容器ip无法访问&#…

22个C语言小白常见问题总结

一.语言使用错误 在打代码的过程中&#xff0c;经常需要在中文与英文中进行转换&#xff0c;因此常出现一些符号一不小心就用错&#xff0c;用成中文。例如&#xff1a;“&#xff1b;”中文中的分号占用了两个字节&#xff0c;而英文中“;”分号只占用一个字节。编译器只能识…

mysql数据库主从复制,搭建从库

1 期望效果 假设我们现在有两个服务器&#xff0c;两个服务器都有数据库&#xff0c;然后我们命名一个叫主数据库&#xff08;Master&#xff09;&#xff0c;一个叫从数据库&#xff08;Slave&#xff09; 数据备份和容灾&#xff1a;通过主从复制&#xff0c;可以将主数据库…

计算机操作系统核心组件

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天给大家讲讲操作系统。 操作系统核心组件 用户借助于一个或多个应用程序与操作系统进行交互&#xff0c;常常是通过一个称为shell的特殊应用程序进行的&#xff0c;shell也叫作命令解释器。105今天的大多…

SQL——SELECT相关的题目

目录 197、上升的温度 577、员工奖金 586、订单最多的客户 596、超过5名学生的课 610、判断三角形 620、有趣的电影 181、超过经理收入的员工 1179、重新格式化部门表 1280、学生参加各科测试的次数 1068、产品销售分析I 1075、项目员工I 1084、销售分析III 1327、列出指…

Qt 报错总结 No suitable kits found

目录 “No suitable kits found” 解决 解决方法参考&#xff1a; chatGPT辅助解决QT构建报错error: multiple target patterns 我的解决方法&#xff1a;把语言设置为空 “No suitable kits found” 解决 没有找到合适的kits套件&#xff0c;在安装Qt Creator时没有安装Min…

程序员做推广?我劝你别干

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 这是卢松松会员专区&#xff0c;一位会员朋友的咨询&#xff0c;如果你也有自研产品&#xff0c;但不知道如何推广&#xff0c;一定要阅读本文!强烈建议收藏关注&#xff0c;因为你关注的人&#xff0c;决定你看到的…

Ubuntu切换内核版本

#安装内核安装工具 sudo apt-get install software-properties-common sudo add-apt-repository ppa:cappelikan/ppa sudo apt-get update sudo apt-get install mainline#安装指定内核版本(有些版本并不能安装成功) mainline install 5.14.10#更新GRUB配置 sudo update-grub#查…

Linux 软件包管理器 yum的下载、功能介绍及使用

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;青果大战linux 总有光环在陨落&#xff0c;总有新星在闪烁 Linux下的三种软件安装方…

burpsuite抓包响应报文乱码

1、响应报文中的中文信息乱码 2、解决办法 3、设置成功后重新发起请求

储油罐智控:ThingsBoard网关实现液位温度精准监测

储油罐是采油、炼油企业储存油品的重要设备&#xff0c;对储油罐液位、温度的实时数据监测对企业的库存和安全管理有着重大意义。 场景 对于企业&#xff0c;尤其是加油站来说&#xff0c;高效的罐体液位、温度监测对于优化燃油库存、防止短缺或过剩至关重要。不准确的燃油液位…

05Django项目--前端公共文件和其他html文件的适配

对应视频链接点击直达 Django项目--前端公共文件和其他html文件的适配 对应视频链接点击直达前端页面准备Pubilc页面设置 OVER&#xff0c;不会有人不会吧不会的加Q1394006513结语 接着上一节 前端页面准备 为了方便大家更好的复制&#xff0c;我把整个项目及templates文件夹和…

RabbitMQ(一)概述第一个应用程序

文章目录 概述AMQP和JMS官网安装开始第一个程序 概述 消息队列是实现应用程序和应用程序之间通信的中间件产品 AMQP和JMS 工作体系 官网 https://www.rabbitmq.com/ RabbitMQ是一款基于AMQP、由Erlang语言开发的消息队列产品 安装 # 拉取镜像 docker pull rabbitmq:3.13-m…

运营抖音小店,这件事情每天都需要去做!一个都不能少!

大家好&#xff0c;我是电商小V 咱们的店铺开好之后&#xff0c;然后运营自己的店铺每天需要做好什么事情呢&#xff1f;这个问题是很多新手小伙伴开通抖店之后最关心的问题&#xff0c;咱们今天就来详细的说一下运营抖音小店每天需要做什么呢&#xff1f; 第一点&#xff1a;奖…