spring+hutool实现简单验证码功能

先看效果

在这里插入图片描述

涉及知识

  • Spring Web
  • DI
  • HuTool
  • Lombok
  • ajax&css&js(前端)

注意:

  1. 本程序使用后端实现,前端代码不做过多解释(提供前端代码)
  2. hutool是一个简单易用的Java工具类库,其中就包含验证码功能:
    官方文档
  3. lombok可以提高开发效率,具体请查看官网:lombok
  4. 本程序就是spring结合hutool进行实现的。

开发步骤

一、定义接口文档

1. 获取验证码

  • 请求方式GET
  • 请求URL/Captcha/getCode
  • 请求参数:无
响应:
  • 响应类型image/jpeg(字节流)
  • 响应内容:返回验证码图片,直接显示在前端页面。

2. 校验验证码

  • 请求方式POST
  • 请求URL/Captcha/check
  • data:captcha=“xxx”(用户输入的验证码)
  • 响应: true或者false(正确/错误)

二、创建spring web项目

导入hutool和lombok的依赖。把两个前端代码拷贝到resources->static路径下:
在这里插入图片描述
然后此路径创建两个包,用于区分代码功能:
在这里插入图片描述
接着,controller路径下创建一个类CaptchaController

在这里插入图片描述

三、CaptchaController的实现

基本框架如下:

package com.hyy.testcaptcha.controller;


import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/Captcha")//根据接口文档建立映射
@RestController//给到spring管理
public class CaptchaController {

    //发送验证码图片给到浏览器
    @GetMapping("/getCode")//根据接口文档建立映射
    public void getCaptcha(
            HttpServletResponse response, //通过http响应把图片发送到浏览器
            HttpSession session) { //创建会话,确定单个用户

    }


    //校验用户输入的验证码是否正确
    @RequestMapping("/check")
    public boolean check(String captcha, //根据接口文档定义,captcha是前端发送过来的用户输入的验证码
                         HttpSession session) {//session中存储此用户相关信息,比如验证码的创建时间,用于判断验证码是否过期

    }
}

getCaptcha方法的实现

注意要引入hutool依赖:

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

方法定义:

 //发送验证码图片给到浏览器
    @GetMapping("/getCode")//根据接口文档建立映射
    public void getCaptcha(
            HttpServletResponse response, //通过http响应把图片发送到浏览器
            HttpSession session) { //创建会话,确定单个用户


        //创建图形验证码,定义长和宽
        ICaptcha icaptcha = CaptchaUtil.createCircleCaptcha(90, 30);

        //定义键值对,Code代表正确的验证码
        session.setAttribute("Code", icaptcha.getCode());
        //设定创建时间 Date()是Java自带的工具类,可以获取创建该对象时的时间戳
        session.setAttribute("Time",new Date());

        //要加异常
        try {
            //规定数据类型
            response.setContentType("image/jpeg");
            //禁止缓存,防止无法向服务器读取图片
            response.setHeader("Pragma", "No-cache");
            //规定编码格式
            response.setCharacterEncoding("utf-8");

            //图片写入浏览器
            icaptcha.write(response.getOutputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

接口测试:
在这里插入图片描述
图片显示成功!

check方法的实现

 //校验用户输入的验证码是否正确
    @RequestMapping("/check")
    public boolean check(String captcha, //根据接口文档定义,captcha是前端发送过来的用户输入的验证码
                         HttpSession session) {//session中存储此用户相关信息,比如验证码的创建时间,用于判断验证码是否过期

        //打印日志
        System.out.println("用户输入的验证码:"+captcha);

        if(captcha==null||captcha=="")return false;//前端返回无效字符串直接返回假

        //校验时间是否过期
        Date before=(Date)session.getAttribute("Time");

        //超时返回假
        if(System.currentTimeMillis()-before.getTime()>OUT_TIME)return false;

        //获取正确的验证码
        String code=(String)session.getAttribute("Code");

        //比对验证码是否正确(不区分大小写)
        return captcha.equalsIgnoreCase(code);
    }

接口测试:
在这里插入图片描述
成功!

至此,后端代码已经全部完成。


优化(解耦合)

一、概述

在这些地方我们的代码是写死的,耦合太强了:

  • 超时时间的定义:
    在这里插入图片描述
  • 长宽的定义:
    在这里插入图片描述
  • 验证码和时间戳名字的定义:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    一旦我们要求改这些参数,会非常麻烦,东改一下,西改以下。所以我们的优化思路是把这些参数放到properties文件中

二、操作步骤

1、修改properties文件

在这里插入图片描述
按照这个配置就可以:

captcha.width=90
captcha.height=30

#超时时间两分钟
captcha.outtime=120000

#session是一个对象,属性分别是time code
captcha.session.date="Time"
captcha.session.code="Code"

2、将properties属性映射到代码

首先,再 mode包中创建一个类CaptchaProperties,作为映射对象:
在这里插入图片描述
代码:

/**
 * 也可以使用@Value一个个映射,但是比较麻烦,所以
 * 我使用ConfigurationProperties
 * */
@Data
@Configuration
@ConfigurationProperties(prefix="captcha")
public class CaptchaProperties {
    private Long outtime;
    private Integer width;
    private Integer height;
    private Session session;

    static class Session{
        String date;
        String code;
    }
}

注意:

  1. 类中属性的名字要和properties配置中的名字要匹配否则会报错!
  2. 内部类必须是static 修饰。因为spring是通过反射创建对象的。但在反射机制中,实例内部类需要创建外部类才能创建。因此,Session是实例内部类,那么Spring无法创建其对象。

然后我们回到CaptchaController,把属性全部替换成CaptchapProperties的对应字段即可:

package com.hyy.testcaptcha.controller;


import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.ICaptcha;
import cn.hutool.captcha.LineCaptcha;
import com.hyy.testcaptcha.mode.CaptchaProperties;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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//给到spring管理
public class CaptchaController {

    //创建属性对象
    @Autowired//依赖注入
    private CaptchaProperties captchaProperties;

    //发送验证码图片给到浏览器
    @GetMapping("/getCode")//根据接口文档建立映射
    public void getCaptcha(
            HttpServletResponse response, //通过http响应把图片发送到浏览器
            HttpSession session) { //创建会话,确定单个用户


        //创建图形验证码,定义长和宽
        ICaptcha icaptcha = CaptchaUtil.createCircleCaptcha(captchaProperties.getWidth(), captchaProperties.getHeight());

        //打印日志
        System.out.println("生成的验证码:"+icaptcha.getCode());

        //定义键值对,Code代表正确的验证码
        session.setAttribute(captchaProperties.getSession().getCode(), icaptcha.getCode());
        //设定创建时间 Date()是Java自带的工具类,可以获取创建该对象时的时间戳
        session.setAttribute(captchaProperties.getSession().getDate(),new Date());

        //要加异常
        try {
            //规定数据类型
            response.setContentType("image/jpeg");
            //禁止缓存,防止无法向服务器读取图片
            response.setHeader("Pragma", "No-cache");
            //规定编码格式
            response.setCharacterEncoding("utf-8");

            //图片写入浏览器
            icaptcha.write(response.getOutputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //超时时间定义成两分钟
    public static Long OUT_TIME=2*60*1000L;

    //校验用户输入的验证码是否正确
    @RequestMapping("/check")
    public boolean check(String captcha, //根据接口文档定义,captcha是前端发送过来的用户输入的验证码
                         HttpSession session) {//session中存储此用户相关信息,比如验证码的创建时间,用于判断验证码是否过期

        //打印日志
        System.out.println("用户输入的验证码:"+captcha);

        if(captcha==null||captcha=="")return false;//前端返回无效字符串直接返回假

        //校验时间是否过期
        Date before=(Date)session.getAttribute(captchaProperties.getSession().getDate());

        //超时返回假
        if(System.currentTimeMillis()-before.getTime()>captchaProperties.getOuttime())return false;

        //获取正确的验证码
        String code=(String)session.getAttribute(captchaProperties.getSession().getCode());

        //比对验证码是否正确(不区分大小写)
        return captcha.equalsIgnoreCase(code);
    }
}

3、测试

URL:

http://127.0.0.1:8080/index.html

输入正确验证码,提交显示成功即可:
在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值