返回顶部
首页 > 资讯 > 精选 >springboot图片验证码功能模块怎么实现
  • 821
分享到

springboot图片验证码功能模块怎么实现

2023-06-30 02:06:10 821人浏览 薄情痞子
摘要

本篇内容主要讲解“SpringBoot图片验证码功能模块怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“springboot图片验证码功能模块怎么实现”吧!具体效果如下:工具类该工具类为生

本篇内容主要讲解“SpringBoot图片验证码功能模块怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习springboot图片验证码功能模块怎么实现”吧!

具体效果如下:

springboot图片验证码功能模块怎么实现

工具

该工具类为生成验证码图片的核心,直接拷贝到项目即可,无需做修改;可个性化的参数全部对外提供的api,比如 字体大小背景颜色,干扰线数量高宽等都可以根据自己的需求设置对应参数;

代码几乎每一行都加了详细的注释;如果遇上特殊的个性化需求,调整一下这个工具类即可实现。

package com.feng.util;import java.awt.*;import java.awt.geom.AffineTransfORM;import java.awt.image.BufferedImage;import java.util.Random;public class VerifyUtil {    // 默认验证码字符集    private static final char[] chars = {            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};    // 默认字符数量    private final Integer SIZE;    // 默认干扰线数量    private final int LINES;    // 默认宽度    private final int WIDTH;    // 默认高度    private final int HEIGHT;    // 默认字体大小    private final int FONT_SIZE;    // 默认字体倾斜    private final boolean TILT;    private final Color BACKGROUND_COLOR;        private VerifyUtil(Builder builder) {        SIZE = builder.size;        LINES = builder.lines;        WIDTH = builder.width;        HEIGHT = builder.height;        FONT_SIZE = builder.fontSize;        TILT = builder.tilt;        BACKGROUND_COLOR = builder.backgroundColor;    }        public static Builder newBuilder() {        return new Builder();    }        public Object[] createImage() {        StringBuffer sb = new StringBuffer();        // 创建空白图片        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);        // 获取图片画笔        Graphics2D graphic = image.createGraphics();        // 设置抗锯齿        graphic.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);        // 设置画笔颜色        graphic.setColor(BACKGROUND_COLOR);        // 绘制矩形背景        graphic.fillRect(0, 0, WIDTH, HEIGHT);        // 画随机字符        Random ran = new Random();        //graphic.setBackground(Color.WHITE);        // 计算每个字符占的宽度,这里预留一个字符的位置用于左右边距        int codeWidth = WIDTH / (SIZE + 1);        // 字符所处的y轴的坐标        int y = HEIGHT * 3 / 4;        for (int i = 0; i < SIZE; i++) {            // 设置随机颜色            graphic.setColor(getRandomColor());            // 初始化字体            Font font = new Font(null, Font.BOLD + Font.ITALIC, FONT_SIZE);            if (TILT) {                // 随机一个倾斜的角度 -45到45度之间                int theta = ran.nextInt(45);                // 随机一个倾斜方向 左或者右                theta = (ran.nextBoolean() == true) ? theta : -theta;                AffineTransform affineTransform = new AffineTransform();                affineTransform.rotate(Math.toRadians(theta), 0, 0);                font = font.deriveFont(affineTransform);            }            // 设置字体大小            graphic.setFont(font);            // 计算当前字符绘制的X轴坐标            int x = (i * codeWidth) + (codeWidth / 2);            // 取随机字符索引            int n = ran.nextInt(chars.length);            // 得到字符文本            String code = String.valueOf(chars[n]);            // 画字符            graphic.drawString(code, x, y);            // 记录字符            sb.append(code);        }        // 画干扰线        for (int i = 0; i < LINES; i++) {            // 设置随机颜色            graphic.setColor(getRandomColor());            // 随机画线            graphic.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT), ran.nextInt(WIDTH), ran.nextInt(HEIGHT));        }        // 返回验证码和图片        return new Object[]{sb.toString(), image};    }        private Color getRandomColor() {        Random ran = new Random();        Color color = new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256));        return color;    }        public static class Builder {        // 默认字符数量        private int size = 4;        // 默认干扰线数量        private int lines = 10;        // 默认宽度        private int width = 80;        // 默认高度        private int height = 35;        // 默认字体大小        private int fontSize = 25;        // 默认字体倾斜        private boolean tilt = true;        //背景颜色        private Color backgroundColor = Color.LIGHT_GRAY;        public Builder setSize(int size) {            this.size = size;            return this;        }        public Builder setLines(int lines) {            this.lines = lines;            return this;        }        public Builder setWidth(int width) {            this.width = width;            return this;        }        public Builder setHeight(int height) {            this.height = height;            return this;        }        public Builder setFontSize(int fontSize) {            this.fontSize = fontSize;            return this;        }        public Builder setTilt(boolean tilt) {            this.tilt = tilt;            return this;        }        public Builder setBackgroundColor(Color backgroundColor) {            this.backgroundColor = backgroundColor;            return this;        }        public VerifyUtil build() {            return new VerifyUtil(this);        }    }}

第二步:图片生成:

使用默认参数:

//生成图片验证码Object[] verify = VerifyUtil.newBuilder().build().createImage();

自定义参数生成:

// 这个根据自己的需要设置对应的参数来实现个性化// 返回的数组第一个参数是生成的验证码,第二个参数是生成的图片Object[] objs = VerifyUtil.newBuilder()        .setWidth(120)   //设置图片的宽度        .setHeight(35)   //设置图片的高度        .setSize(6)      //设置字符的个数        .setLines(10)    //设置干扰线的条数        .setFontSize(25) //设置字体的大小        .setTilt(true)   //设置是否需要倾斜        .setBackgroundColor(Color.WHITE) //设置验证码的背景颜色        .build()         //构建VerifyUtil项目        .createImage();  //生成图片

整合到springboot项目中:

需要引入的Maven依赖:

        <!--redis相关配置-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-Redis</artifactId>        </dependency>        <!-- redis 连接池 -->        <!--新版本连接池lettuce-->        <dependency>            <groupId>org.apache.commons</groupId>            <artifactId>commons-pool2</artifactId>        </dependency>        <!-- 图形验证码 -->        <dependency>            <groupId>net.jodah</groupId>            <artifactId>expiringmap</artifactId>            <version>0.5.10</version>        </dependency>

获取相关的验证码:

service层:

package com.feng.service;import org.cuit.epoch.result.Result;import javax.servlet.Http.httpservletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public interface VerifyService {        void createCode(HttpServletResponse response, HttpServletRequest request) throws IOException;        Result<String> checkCode(String verificationCode);}

serviceimpl层:

package com.feng.service.impl;import com.feng.service.VerifyService;import com.feng.util.RedisServiceImpl;import com.Google.common.net.HttpHeaders;import com.feng.util.VerifyUtil;import org.springframework.http.ResponseCookie;import org.springframework.stereotype.Service;import javax.annotation.Resource;import javax.imageio.ImageIO;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.awt.image.BufferedImage;import java.io.IOException;import java.io.OutputStream;import java.time.Duration;@Servicepublic class VerifyServiceImpl implements VerifyService {    @Resource    RedisServiceImpl redisUtil;        @Override    public void createCode(HttpServletResponse response, HttpServletRequest request) throws IOException {        //获取session        HttpSession session = request.getSession();        //获得sessionId        String id = session.getId();        System.out.println();        ResponseCookie cookie = ResponseCookie.from("JSESSIONID",id)                .secure(true)                .domain("")                .path("/")                .maxAge(Duration.ofHours(1))                .sameSite("None")                .build();        //清除之前缓存的图片验证码        if (!String.valueOf(request.getSession().getAttribute("SESSION_VERIFY_CODE_"+id)).isEmpty()){            String getVerify = String.valueOf(request.getSession().getAttribute("SESSION_VERIFY_CODE_"+id));            redisUtil.del(getVerify);            System.out.println("清除成功");        }        //生成图片验证码,用的默认参数        Object[] verify = VerifyUtil.newBuilder().build().createImage();        //将验证码存入session        session.setAttribute("SESSION_VERIFY_CODE_" + id, verify[0]);        //打印验证码        System.out.println(verify[0]);        //将验证码存入redis        redisUtil.set((String) verify[0],id,5*60);        //将图片传给浏览器        BufferedImage image = (BufferedImage) verify[1];        response.setContentType("image/png");        response.setHeader(HttpHeaders.SET_COOKIE,cookie.toString());        OutputStream ops = response.getOutputStream();        ImageIO.write(image,"png",ops);    }    @Override    public Result<String> checkCode(String verificationCode){        if (!redisUtil.hasKey(verificationCode)){            return new Result<>(false,"验证码错误");        }        redisUtil.del(verificationCode);        return R.success();    }}

这里面还会用到redis相关的工具类,我就不列出来了,想要的话可以看我以前的博客工具类戳这里

controller层:
这里有用到@RequiredArgsConstructor, 就是简单的注入而已, 如果想要详细了解戳这里

package com.feng.controller;import lombok.RequiredArgsConstructor;import com.feng.annotation.LimitRequest;import com.feng.service.VerifyService;import org.springframework.WEB.bind.annotation.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;@RestController@RequestMapping("/verify")@RequiredArgsConstructor//这是在lombok工具给的注入方式,真帅public class VerifyController {    private final VerifyService verifyService;        @LimitRequest(count = 5)//这个注解就是表示, 你在限制时间里(我们这里默认是六秒钟), 只能请求五次    @GetMapping("/getCode")    public void getCode(HttpServletResponse response, HttpServletRequest request) throws IOException {        verifyService.createCode(response, request);    }    @LimitRequest(count = 5)//这个注解就是表示, 你在限制时间里(我们这里默认是六秒钟), 只能请求五次    @GetMapping("/checkCode")    public Result<String> checkCode(String code){        return verifyService.checkCode(code);    }}

这里为了不被一直无限制的访问该服务, 我们用了一个限制ip访问次数的注解@LimitRequest

annotion包下的注解类:

package com.feng.annotation;import java.lang.annotation.*;@Documented@Target(ElementType.METHOD) // 说明该注解只能放在方法上面@Retention(RetentionPolicy.RUNTIME)public @interface LimitRequest {    long time() default 6000; // 限制时间 单位:毫秒    int count() default 3; // 允许请求的次数}

aspect包下的切面类:

package com.feng.aspect;import net.jodah.expiringmap.ExpirationPolicy;import net.jodah.expiringmap.ExpiringMap;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import com.feng.annotation.LimitRequest;import org.cuit.epoch.exception.AppException;import org.springframework.stereotype.Component;import org.springframework.web.context.request.RequestAttributes;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.TimeUnit;@Aspect@Componentpublic class LimitRequestAspect {    private static ConcurrentHashMap<String, ExpiringMap<String, Integer>> book = new ConcurrentHashMap<>();    // 定义切点    // 让所有有@LimitRequest注解的方法都执行切面方法    @Pointcut("@annotation(limitRequest)")    public void excudeService(LimitRequest limitRequest) {    }    @Around("excudeService(limitRequest)")    public Object doAround(ProceedingJoinPoint pjp, LimitRequest limitRequest) throws Throwable {        // 获得request对象        RequestAttributes ra = RequestContextHolder.getRequestAttributes();        ServletRequestAttributes sra = (ServletRequestAttributes) ra;        HttpServletRequest request = sra.getRequest();        // 获取Map对象, 如果没有则返回默认值        // 第一个参数是key, 第二个参数是默认值        ExpiringMap<String, Integer> uc = book.getOrDefault(request.getRequestURI(), ExpiringMap.builder().variableExpiration().build());        Integer uCount = uc.getOrDefault(request.getRemoteAddr(), 0);        if (uCount >= limitRequest.count()) { // 超过次数,不执行目标方法            System.out.println("接口请求超过次数!");            throw new AppException("接口请求超过次数!");        } else if (uCount == 0) { // 第一次请求时,设置有效时间//            uc.put(request.getRemoteAddr(), uCount + 1, ExpirationPolicy.CREATED, limitRequest.time(), TimeUnit.MILLISECONDS);        } else { // 未超过次数, 记录加一            uc.put(request.getRemoteAddr(), uCount + 1);        }        book.put(request.getRequestURI(), uc);        // result的值就是被拦截方法的返回值        Object result = pjp.proceed();        return result;    }}

为了捕获全局的异常抛出, 且符合restful规范我们加一个这个处理类:

handle包下面的全局异常类:

package org.cuit.epoch.handler;import lombok.extern.log4j.Log4j2;import org.cuit.epoch.exception.AppException;import org.cuit.epoch.result.R;import org.cuit.epoch.result.Result;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;@ControllerAdvice@Log4j2public class GlobalExceptionHandler {    @ExceptionHandler(Exception.class)    @ResponseBody    public Result error(Exception e) {        log.error(e.getMessage());        e.printStackTrace();        return R.fail(e.getMessage());    }    @ExceptionHandler(AppException.class)    @ResponseBody    public Result error(AppException e) {        log.error(e.getMessage());        e.printStackTrace();        return R.fail(e.getMessage());    }}

application.yaml文件:

spring:  cache:    type:      redis  redis: #redis连接配置    host: 自己redis的ip地址    port: redis端口    passWord: 密码    jedis:      pool:        max-active: 8        max-wait: -1ms        max-idle: 500        min-idle: 0    lettuce:      shutdown-timeout: 0ms

最终项目结构如下:

springboot图片验证码功能模块怎么实现

先得到一个验证码:

springboot图片验证码功能模块怎么实现

验证一下是否成功:

成功结果:

springboot图片验证码功能模块怎么实现

验证失败结果:

springboot图片验证码功能模块怎么实现

当请求在规定时间内的请求数超过规定的数量时或有报错:

springboot图片验证码功能模块怎么实现

到此,相信大家对“springboot图片验证码功能模块怎么实现”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: springboot图片验证码功能模块怎么实现

本文链接: https://lsjlt.com/news/327224.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • springboot图片验证码功能模块怎么实现
    本篇内容主要讲解“springboot图片验证码功能模块怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“springboot图片验证码功能模块怎么实现”吧!具体效果如下:工具类该工具类为生...
    99+
    2023-06-30
  • springboot图片验证码功能模块
    目录前言:第一步:工具类第二步:图片生成:整合到springboot项目中:前言: 大家好!我是小小!今天我们用五分钟来用springboot实现我们常用的图形验证码功能模块! 用户...
    99+
    2024-04-02
  • 基于Hutool的图片验证码功能模块实现
    目录简介Hutool名称的由来基于Hutool的图片验证码功能模块实现1.背景2.方案设计2.1 方案步骤2.2 Hutool工具类引入2.5 方案交互图3.模块编写4.接口测试简介...
    99+
    2022-11-13
    Hutool图片验证码 Hutool图片验证码
  • 怎么用Springboot +redis+Kaptcha实现图片验证码功能
    这篇文章主要介绍了怎么用Springboot +redis+Kaptcha实现图片验证码功能的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么用Springboot +redis+Kaptc...
    99+
    2023-06-29
  • SpringBoot整合kaptcha实现图片验证码功能
    目录栗子配置文件SpringBoot项目中pom.xml文件项目代码项目结构SpringBootVerifyCodeApplication.javaVerifyCodeConfig....
    99+
    2024-04-02
  • JS实现图片验证码功能
    本文实例为大家分享了JS实现图片验证码功能的具体代码,供大家参考,具体内容如下 以下代码可以直接copy运行,不需要引入jquery.jar 1. html代码 <%@ pag...
    99+
    2024-04-02
  • Java实现图片验证码功能
    简介 在实现登录功能时,一般为了安全都会设置验证码登录,为了防止某个用户用特定的程序暴力破解方式进行不断的尝试登录。常见验证码分为图片验证码和短信验证码,还有滑动窗口模块和选中指定物...
    99+
    2024-04-02
  • SpringBoot实现滑块验证码验证登陆校验功能详解
    目录前言一、实现效果二、实现思路三、实现步骤1. 后端 java 代码1.1 新建一个拼图验证码类1.2 新建一个拼图验证码工具类1.3 新建一个 service 类1.4 新建一个...
    99+
    2024-04-02
  • Springboot +redis+谷歌开源Kaptcha实现图片验证码功能
    背景 注册-登录-修改密码一般需要发送验证码,但是容易被攻击恶意调⽤什么是短信-邮箱轰炸机手机短信轰炸机是批、循环给手机无限发送各种网站的注册验证码短信的方法。公司带来的损失短信1条...
    99+
    2024-04-02
  • springboot验证码生成及验证功能怎么实现
    这篇“springboot验证码生成及验证功能怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“springboot验证...
    99+
    2023-07-06
  • jsp实现简单图片验证码功能
    本文实例为大家分享了jsp实现简单图片验证码的具体代码,供大家参考,具体内容如下 一、实现的功能分析 (1)在登陆页面加验证码的功能,起到一定的安全性。在输入正确的验证码,用户名和密...
    99+
    2024-04-02
  • JS如何实现图片验证码功能
    本篇内容主要讲解“JS如何实现图片验证码功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JS如何实现图片验证码功能”吧!1. html代码<%@ page langu...
    99+
    2023-06-30
  • springboot+vue实现验证码功能
    本文实例为大家分享了springboot+vue实现验证码功能的具体代码,供大家参考,具体内容如下 1.工具类 直接用不用改 package com.example.demo.U...
    99+
    2024-04-02
  • Springboot+SpringSecurity怎么实现图片验证码登录
    本文小编为大家详细介绍“Springboot+SpringSecurity怎么实现图片验证码登录”,内容详细,步骤清晰,细节处理妥当,希望这篇“Springboot+SpringSecurity怎么实现图片验证码登录”文章能帮助大家解决疑惑...
    99+
    2023-06-30
  • Flutter怎么实现滑动块验证码功能
    这篇文章主要介绍“Flutter怎么实现滑动块验证码功能”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Flutter怎么实现滑动块验证码功能”文章能帮助大家解决问题。本文实现的是一个用于登录时,向右...
    99+
    2023-06-29
  • Android 如何实现滑块拼图验证码功能
    本篇内容主要讲解“Android 如何实现滑块拼图验证码功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android 如何实现滑块拼图验证码功能”吧!本篇主要从两方面进行介绍:使用依赖库实现...
    99+
    2023-06-14
  • php怎么实现图片验证码
    本文操作环境:Windows7系统、PHP7.1版,DELL G3电脑。php怎么实现图片验证码?PHP实现图片验证码功能验证码: captcha, 是一种用于区别人和电脑的技术原理(Completely Automated Public ...
    99+
    2017-09-20
    php
  • vue 实现左滑图片验证功能
    目录前言一、安装二、使用前言 众所周知,网页中滑动图片验证一直是各大网站、移动端的主流校验方式,其主要作用是为了区分人和机器以及为了防止机器人程序暴力登录或攻击从而设置的一种安全保护...
    99+
    2023-05-14
    vue 左滑图片验证 vue 图片验证 vue 左滑验证
  • SpringSecurity实现添加图片验证功能
    目录本章内容思路方案怎么将字符串变成图片验证码kaptcha这么玩hutool这么玩传统web项目过滤器方式认证器方式总结下前后端分离项目基于过滤器方式基于认证器方式本章内容 Spr...
    99+
    2023-01-04
    Spring Security添加图片验证 Spring Security图片验证
  • vue实现图片滑动验证功能
    图片滑动验证,是目前比较常见的验证方式,主要目的是防止用户利用机器人自动注册、登录、灌水。 目前vue技术日趋成熟,已经有专门针对图片滑动验证功能的插件了。具体使用方式如下: 1....
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作