【Spring】Spring Boot 验证码小项目:Hutool 让图形验证码开发变简单


🎬 那我掉的头发算什么个人主页
🔥 个人专栏 : 《javaSE》《数据结构》《数据库》《javaEE》

⛺️待到苦尽甘来日


文章目录

验证码小项目

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

需求

界面如下图所示

1.页面生成验证码

2.输入验证码,点击提交,验证用户输入验证码是否正确,正确则进行页面跳转

约定前后端交互接口

后端需要提供两个服务

1.生成验证码,并返回验证码

2.校验验证码是否正确:校验验证码是否正确.

接口定义:

1.生成验证码

请求:/captcha/getcaptcha

响应:验证码图片内容

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

2.校验验证码是否正确

请求: /captcha/check

响应: true/false

根据用户输入的验证码,校验验证码是否正确.

true: 验证成功. false: 验证失败

Hutool工具介绍

咱们课程中验证码的实现,使用 Hutool 提供的小工具来实现

Hutool 是一个 Java 工具包类库,对文件、流、加密解密、转码、正则、线程、XML 等 JDK 方法进行封装,组成各种 Util 工具类.

Hutool 是一个小而全的 Java 工具类库,通过静态方法封装,降低相关 API 的学习成本,提高工作效率,使 Java 拥有函数式语言般的优雅,让 Java 语言也可以 "甜甜的"

地址:

https://doc.hutool.cn/pages/ai/#概述

配置

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

这是我从官网上摘下来的配置,懒人模式,一键导入所有huTool的依赖,否则需要找到对应的模块单独引入。

使用

java 复制代码
//定义图形验证码的长和宽
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);

//图形验证码写出,可以写出到文件,也可以写出到流
lineCaptcha.write("d:/line.png");
//输出code
Console.log(lineCaptcha.getCode());
//验证图形验证码的有效性,返回boolean值
lineCaptcha.verify("1234");

//重新生成验证码
lineCaptcha.createCode();
lineCaptcha.write("d:/line.png");
//新的验证码
Console.log(lineCaptcha.getCode());
//验证图形验证码的有效性,返回boolean值
lineCaptcha.verify("1234");

然后就可以去找到Captcha模块,使用提供好的代码了。

当然,为了实现我们自己的前后端交互,肯定要对它的代码进行修改。

使用Hutool完成验证码项目

定义的验证码类:

java 复制代码
package com.hbu.captchademo.CaptchaProperties;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;

@ConfigurationProperties(prefix = "captcha")
@Component
@Data
public class MyCaptcha {
    private Integer width;
    private Integer height;
    private Session session;

    @Data
    public static class Session{
        private String key;
        private String date;
    }
}

yml配置文件:

java 复制代码
spring:
  application:
    name: captcha-demo

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

Controller:

java 复制代码
package com.hbu.captchademo.Controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.lang.Console;
import cn.hutool.extra.spring.SpringUtil;
import com.hbu.captchademo.CaptchaProperties.MyCaptcha;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.val;
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;

@RequestMapping("/captcha")
@RestController
public class CaptchaController {
    @Autowired
    private MyCaptcha myCaptcha;
    private final static long VALID_TIME = 60*1000L;

    @RequestMapping("/getCaptcha")
    public void getCaptcha(HttpSession session, HttpServletResponse response) throws IOException {
        response.setContentType("image/png");
        //定义图形验证码的长和宽
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(myCaptcha.getWidth(), myCaptcha.getHeight());
        String code = lineCaptcha.getCode();
        session.setAttribute(myCaptcha.getSession().getKey(),code);
        session.setAttribute(myCaptcha.getSession().getDate(),new Date());
        //图形验证码写出,可以写出到文件,也可以写出到流
        lineCaptcha.write(response.getOutputStream());
    }

    @RequestMapping("/check")
    public Boolean check(String captcha,HttpSession session){
        if(!StringUtils.hasLength(captcha)){
            return false;
        }
        String code = (String)session.getAttribute(myCaptcha.getSession().getKey());
        Date date = (Date)session.getAttribute(myCaptcha.getSession().getDate());
        if(code!=null&&code.equalsIgnoreCase(captcha)&&date!=null&&System.currentTimeMillis()-date.getTime()<VALID_TIME){
            return true;
        }
        return false;
    }
}

前端代码:

java 复制代码
<!DOCTYPE html>
<html lang="en">

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

    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Expires" content="0" />

    <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/getCaptcha" 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/getCaptcha?dt=' + new Date().getTime()).fadeIn();
    });

    $("#checkCaptcha").click(function () {
        $.ajax({
            type: "post",
            url: "/captcha/check",
            data: {
                captcha: $("#inputCaptcha").val()
            },
            success: function(result){
                if(result){
                    location.href = "success.html";
                }else {
                    alert("验证码错误, 请重新输入");
                }
            }
        });
    });

</script>
</body>

</html>
java 复制代码
<!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>


以上就是本篇博客全部内容!

相关推荐
木辰風4 小时前
PLSQL自定义自动替换(AutoReplace)
java·数据库·sql
heartbeat..4 小时前
Redis 中的锁:核心实现、类型与最佳实践
java·数据库·redis·缓存·并发
i建模4 小时前
在 Rocky Linux 上安装轻量级的 XFCE 桌面
linux·运维·服务器
5 小时前
java关于内部类
java·开发语言
好好沉淀5 小时前
Java 项目中的 .idea 与 target 文件夹
java·开发语言·intellij-idea
gusijin5 小时前
解决idea启动报错java: OutOfMemoryError: insufficient memory
java·ide·intellij-idea
To Be Clean Coder5 小时前
【Spring源码】createBean如何寻找构造器(二)——单参数构造器的场景
java·后端·spring
吨~吨~吨~5 小时前
解决 IntelliJ IDEA 运行时“命令行过长”问题:使用 JAR
java·ide·intellij-idea
你才是臭弟弟5 小时前
SpringBoot 集成MinIo(根据上传文件.后缀自动归类)
java·spring boot·后端
短剑重铸之日5 小时前
《设计模式》第二篇:单例模式
java·单例模式·设计模式·懒汉式·恶汉式