【Spring】探秘 SpringBoot 配置文件:解锁验证码背后的实现逻辑

前言

🌟🌟本期讲解关于Spring IOC&DI的详细介绍~~~

🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客

🔥 你的点赞就是小编不断更新的最大动力

🎆那么废话不多说直接开整吧~~

目录

📚️1.验证码案例要求

1.1实例展示

1.2需求

1.3前后端接口定义

📚️2.Hutool的使用

2.1Hutool的内容介绍

2.2Hutool验证码

2.3线段干扰验证码

2.4圆圈干扰验证码

📚️3.验证码实现

3.1生成验证码

3.2检验验证码

3.3配置文件的使用

3.4前端代码

📚️4.总结


📚️1.验证码案例要求

1.1实例展示

我们经常在平时的登录等界面的时候,就会出现验证码,具体的格式如下所示:

可以看到此时我们的验证码有很多类型大致可分为以下几类:

干扰项:圆形干扰,线性干扰,扭曲字体干扰,颜色色块干扰.....其实主要就是验证码号以及背景干扰项;(小编自己总结的)

那么我们就需要使用一定的功能的包来实现这些具体的功能,后面小编会提及到;

1.2需求

界⾯如下图所⽰

  1. ⻚⾯⽣成验证码

  2. 输⼊验证码, 点击提交, 验证⽤⼾输⼊验证码是否正确, 正确则进⾏⻚⾯跳转

1.3前后端接口定义

需求分析后端需要提供两个服务

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

接⼝定义

  1. ⽣成验证码

请求:

请求URL: /Captcha/getCaptcha

响应: 验证码图⽚内容

浏览器给服务器发送⼀个 /captcha/getCaptcha 这样的请求, 服务器返回⼀个图⽚, 浏览器显

⽰在⻚⾯上

2.检验验证码

请求:

请求URL:/Captcha/check

参数:这里就是用户输入的验证码

响应:返回true或者false

然后前端根据这里的返回的布尔类型进行对应界面响应的显示;

📚️2.Hutool的使用

Hutool是⼀个Java⼯具包类库,对⽂件、流、加密解密、转码、正则、线程、XML等JDK⽅法进⾏封装,组成各种Util⼯具类.

Hutool是⼀个⼩⽽全的Java⼯具类库,通过静态⽅法封装,降低相关API的学习成本,提⾼⼯作效

率,使Java拥有函数式语⾔般的优雅,让Java语⾔也可以"甜甜的

界面图示如下:

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

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

Hutool源码: https://github.com/dromara/hutool

2.1Hutool的内容介绍

Hutool的目标是使用一个工具方法代替一段复杂代码,从而最大限度的避免"复制粘贴"代码的问题,彻底改变我们写代码的方式。

以计算MD5为例:

  • 👴【以前】打开搜索引擎 -> 搜"Java MD5加密" -> 打开某篇博客-> 复制粘贴 -> 改改好用
  • 👦【现在】引入Hutool -> SecureUtil.md5()

可以看到其实就是引入一个包,然后使用一系列的方法来实现这里的验证码;

其中组件介绍了包含的各个部分功能的模块介绍,但是懒得一个一个看那么就直接使用总的包来实现,所以这里我们就要引入Hutool的Maven的依赖,这里在官方也说明了如何进行使用

代码如下所示:

XML 复制代码
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>

注意:

一定是在pom文件进行依赖的引入,一定一定要记得刷新这里的Maven;

2.2Hutool验证码

在hutool参考文档中,在搜索框里搜索验证码,然后就会出现如下的界面:

可以看到这里就是教我们如何在后端中使用创建一个验证码(这里就是一个线段干扰的验证码),往下翻就会看到其他的验证码,小编稍微讲解一两个

2.3线段干扰验证码

我们如何构造线段干扰验证码,直接复制粘贴,所有伟大的程序员都是"Ctrl C Ctrl V"的高手,有资源不用,自己打就很慢,而且可能会出现错误;

代码如下:

java 复制代码
@RestController
@RequestMapping("/get")
public class Captcha {
    @RequestMapping("/Captcha")
    public void createCaptcha(){
        //定义图形验证码的长和宽
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
        lineCaptcha.write("E:/line.png");
        Console.log(lineCaptcha.getCode());
        lineCaptcha.verify("1234");


        lineCaptcha.createCode();       
        lineCaptcha.write("E:/line.png");
        Console.log(lineCaptcha.getCode());
        lineCaptcha.verify("1234");
    }
}

解释:

++1. 具体就是先//定义图形验证码的长和宽,这里包含了创建一个验证码,然后写入到文件中,当然这里也可以写入到流中;++

++2.然后再控制台打印,拿到这里生成的验证码,当然这里也可以不进行打印;++

++3.最后这里就是通过verify进行比较验证的操作;++

生成的验证码图片如下:

2.4圆圈干扰验证码

具体的代码在hutool官网上,下面小编就摘抄下来演示演示:

java 复制代码
@RequestMapping("/get")
public class Captcha {
    @RequestMapping("/Captcha")
    public void createCaptcha(){
      
        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20);
        captcha.write("E:/line.png");
        captcha.verify("1234");
    }
}

解释:

++这里和上面的操作几乎是一致的,这里创建的就是圆形干扰项,然后写入到文件中,最后进行了比较,当然这里可以在控制台进行打印日志++

运行后,进行http访问后在E盘就可以看到如下图:

可以看到很明显的圆形干扰项,好了hutool的验证码使用就介绍到这里,小编就不再进行多余的演示了,大家可以自己去玩一玩;

📚️3.验证码实现

3.1生成验证码

经过上面的操作,大致对于验证码的实现有了一定的理解,然后我们根据上面的接口的定义,来实现一下后端代码;

实现验证码的生成,代码如下所示:

java 复制代码
@RestController
@RequestMapping("/Captcha")
public class HuToolCaptchaController {
    private final static long session_captcha_timeout=60*1000;
    @Autowired
    private Constants constants;
    @RequestMapping("/getCaptcha")
    public void getCaptcha(HttpServletResponse response, HttpSession session){
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
        //图形验证码写出,可以写出到文件,也可以写出到流
        try {

            lineCaptcha.write(response.getOutputStream());
            System.out.println(lineCaptcha.getCode());
            session.setAttribute(constants.getKey(),lineCaptcha.getCode());
            session.setAttribute(constants.getDate(),System.currentTimeMillis());
            response.getOutputStream().close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

这里的代码有点杂乱,小编一一解释一下:

1.首先小编这里设置60*1000就是代表的60秒的意思,平时我们使用获取验证码后会有一个限制的时间,这里就是60秒的限时;

2.然后很明显这里小编进行了对象的引入的操作,这里就是代表有一个类中有我们需要的数据;

3.我们要获取验证码以流的形式展示在浏览器上,所以在响应的过程中就会使用到response,来进行outputstrewam,然后就是生成一个线段的干扰验证码,;

4.之后我们要将这里的验证码,传给下面的检查的后端代项目,这里用session存储是因为每个客户端是通过一个sessionID来获取session,是唯一的;

5.然后这里有存储了创建验证码的时间,主要是为了获取重用户输入到生成验证码的时间差,若大于60秒,则该有什么逻辑,或者小于该有什么逻辑;

6.当数据通过OutputStream写入到响应流后,它可以释放与这个流相关的系统资源,如文件描述符、网络套接字等。如果不关闭流,可能会导致资源泄漏,特别是在高并发的场景下,可能会耗尽系统资源。

3.2检验验证码

注意这里的检验验证码和上面的生成是有一定的联系的,具体的代码如下所示:

java 复制代码
 @RequestMapping("/check")
    public boolean check(String inputCode,HttpSession session){
        if(!StringUtils.hasLength(inputCode)){
            return false;
        }
        String savedCode=(String) session.getAttribute(constants.getKey());
        long savedTime=(Long) session.getAttribute(constants.getDate());
        if (inputCode.equalsIgnoreCase(savedCode)){
            if(savedCode!=null && System.currentTimeMillis()-savedTime < session_captcha_timeout){
                return true;
            }
        }
        return false;
    }

解释:

1.接收这里的用户输入的参数的设置,然后还有session来获取对应的时间戳或者验证码;

2.这里就是通过sessionid来获取这里的验证码,在获取这里此时的时间;

3.最后通过比较用户输入的数据以及正确验证码的内容,注意这里的equals是要忽略大小写的;

4.if语句判断,若收到验证码,并且这里的用户输入和生成验证码的时间小于60秒就返回true,反之返回false;

3.3配置文件的使用

小编这里由于这里的验证码以及时间是同一个数据,这里就以将这里验证码和时间作为配置文件的数据来写入到配置文件中,然后用对象来进行获取;

java 复制代码
captcha:
  key: CAPTCHA_SESSION_KEY
  date: CAPTCHA_SESSION_TIME

然后通过对象来进行接收这里的配置文件数据:

java 复制代码
@Component
@ConfigurationProperties(prefix = "captcha")
@Data
public class Constants {
    private String key;
    private String date;
}

注意:

这里的对象接收注解就是通过@ConfigurationProperties进行接收,普通数据是通过value进行接收的,以及这里的的注解Data,可以通过target进行查看反编译文件:

java 复制代码
@Component
@ConfigurationProperties(
    prefix = "captcha"
)
public class Constants {
    private String key;
    private String date;
    @Generated
    public Constants() {
    }
    @Generated
    public String getKey() {
        return this.key;
    }
    @Generated
    public String getDate() {
        return this.date;
    }
    @Generated
    public void setKey(final String key) {
        this.key = key;
    }
    @Generated
    public void setDate(final String date) {
        this.date = date;
    }

解释:

可以看到此时这里的代码已经进行重写的操作,但是:注意由于spring更新了,创建项目的时候会添加lombok依赖时,会自动引入一个插件,要把这里的插件进行删除操作:

如下所示:

XML 复制代码
<build>
        <plugins>
            <!--<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>-->
            <plugin>

这就是我们需要注释掉的代码;

为啥要注释掉这里的代码呢?在实验的过程中小编发现,若不注释掉这里的代码可能就会出现@Data注释不帮我们构造这里的set与get方法,就会导致编译时没有错误,但是一旦运行就会出现报错的情况;

3.4前端代码

具体的代码如下:

javascript 复制代码
 $("#verificationCodeImg").click(function(){
      $(this).hide().attr('src', '/Captcha/getCaptcha?dt=' + new Date().getTime()).fadeIn();
    });

    $("#checkCaptcha").click(function () {
       $.ajax({
         url:"Captcha/check",
         type:"post",
         data:{
           inputCode:$("#inputCaptcha").val(),
         },
         success:function (result){
           if (result){
             location.href="success.html"
           }else {
             alert("验证码有误或者验证时间超时")
           }
         }
       })

解释:

这里的第一个点击图片就是刷新图片,然后后面跟时间,是为了防止这里前端进行缓存的操作,然后第二个点击操作是进行验证码的检验,是否正确,这里是通过ajax进行方法操作,并接收这里的参数;

📚️4.总结

本期小编主要是实现了关于验证码的后端代码的实现,并介绍了这里的Hutool的使用,当然Hutool不仅限于验证码还有其他的功能,大家可以去玩一玩~~~

验证码的代码我已经上传Gitee咯:Captcha: 验证码代码(包括前后端)

🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!


💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。

😊😊 期待你的关注~~~

相关推荐
m0_548514771 小时前
前端打印功能(vue +springboot)
前端·vue.js·spring boot
customer082 小时前
【开源免费】基于SpringBoot+Vue.JS加油站管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·maven
Hello.Reader2 小时前
Spring Retry 与 Redis WATCH 结合实现高并发环境下的乐观锁
java·redis·spring
西岭千秋雪_2 小时前
设计模式の单例&工厂&原型模式
java·单例模式·设计模式·简单工厂模式·工厂方法模式·抽象工厂模式·原型模式
fanchael_kui3 小时前
使用elasticsearch-java客户端API生成DSL语句
java·大数据·elasticsearch
m0_748256563 小时前
[CTF夺旗赛] CTFshow Web1-14 详细过程保姆级教程~
java
T.O.P113 小时前
Spring&SpringBoot常用注解
java·spring boot·spring
O(1)的boot3 小时前
微服务的问题
java·数据库·微服务
一个略懂代码的程序员3 小时前
Redis01
java·redis
IT界的奇葩4 小时前
基于springboot使用Caffeine
java·spring boot·后端·caffeine