springboot实现验证码功能

转载自 : www.javaman.cn

1、编写工具类生成4位随机数

该工具类主要生成从0-9,a-z,A-Z范围内产生的4位随机数

/**
     * 产生4位随机字符串
     */
    public static String getCheckCode() {
        String base = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        int size = base.length();
        Random r = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 1; i <= 4; i++) {
            //产生0到size-1的随机值
            int index = r.nextInt(size);
            //在base字符串中获取下标为index的字符
            char c = base.charAt(index);
            //将c放入到StringBuffer中去
            sb.append(c);
        }
        return sb.toString();
    }
2、编写常量类

用户常量的绑定,所有的常量都可以在ConfigConsts中定义,方便管理。

import java.util.Arrays;
import java.util.List;

public interface ConfigConsts {
    /**
     * 验证码存session
     */
    String IMAGE_CODE_SESSION = "IMAGE_CODE";
}
3、获取验证码接口

这段代码的主要作用是为用户生成一个图片验证码,并将其显示在浏览器中。当调用该代码对应的URL时,服务器会创建一个包含随机验证码的图片,并将此验证码存储在用户的会话中,然后将该图片发送给用户的浏览器显示

     /**
     * 验证码
     */
    @RequestMapping("/getImgCode")
    public void getImgCode(HttpServletRequest request, HttpServletResponse response) {
        int width = 80;
        int height = 30;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //获取画笔
        Graphics graphics = image.getGraphics();
        //设置画笔颜色为白色
        graphics.setColor(Color.white);
        //填充图片
        graphics.fillRect(0, 0, width, height);
        //设置画笔颜色为黑色
        graphics.setColor(Color.black);
        //设置字体的小大
        graphics.setFont(new Font("黑体", Font.BOLD, 24));
        //产生4个随机验证码
        String checkCode = CommonUtil.getCheckCode();
        //将验证码放入HttpSession中
        HttpSession session = request.getSession();
        session.setAttribute(ConfigConsts.IMAGE_CODE_SESSION, checkCode);
        //向图片上写入验证码
        graphics.drawString(checkCode, 15, 25);
        //将内存中的图片输出到浏览器
        try {
            response.setContentType("image/png");
            ImageIO.write(image, "PNG", response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
4、controller跳转到登录页

对“/loginPage”的GET请求,并将用户重定向到登录页面。当调用这个URL时,系统会返回一个名为"login"的视图(通常是一个HTML页面),这个视图通常用于显示登录表单,让用户输入用户名和密码等信息。

    /**
     * 跳转到登陆页面
     * @return 登陆页面
     */
    @GetMapping("/loginPage")
    public String loginPage(){
        return "login";
    }
5、登录界面

在Web页面上实现一个图形验证码的输入功能

  1. HTML部分
    • 创建一个表单项,内部包含两列(使用layui的栅格系统)。
    • 在第一列中,有一个标签和一个文本输入框。标签用于显示一个验证码图标,输入框用于用户输入图形验证码。
    • 在第二列中,有一个图片元素用于显示图形验证码图片。
  2. JavaScript部分
    • 配置layui的静态资源路径和主入口模块。
    • 初始化时,调用getImgCode函数加载验证码图片,并渲染表单。
    • getImgCode函数通过Ajax请求从服务器获取验证码图片,并将其显示在页面上的图片元素中。

这段代码主要利用了layui框架来实现页面的布局和交互,同时通过JavaScript和Ajax实现与服务器的通信,以获取并显示图形验证码。

<div class="layui-form-item">
    <div class="layui-row">
        <div class="layui-col-xs7">
            <label class="layadmin-user-login-icon layui-icon layui-icon-vercode"></label>
            <input type="text" name="code"  lay-verify="required" placeholder="图形验证码" class="layui-input">
        </div>
        <div class="layui-col-xs5">
            <div style="margin-left: 10px;">
                
                <img id="codeImg" class="layadmin-user-login-codeimg">
            </div>
        </div>
    </div>
    
    <script>
 	layui.config({
        base: '/static/layuiadmin/' //静态资源所在路径
    }).extend({
        index: 'lib/index' //主入口模块
    }).use(['index', 'user'], function(){
        let $ = layui.$,
            form = layui.form;
        // 初始化
        getImgCode();
        form.render();
    }
    /**
     * 获取验证码
     */
    function getImgCode() {
        let url = ctx + '/getImgCode';
        let xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.responseType = "blob";
        xhr.onload = function() {
            if (this.status === 200) {
                let blob = this.response;
                document.getElementById("codeImg").src = window.URL.createObjectURL(blob);
            }
        }
        xhr.send();
    }
    </script>
6、验证码过滤

校验验证码的过滤器,基于Java的Spring框架。

  1. 该过滤器继承了OncePerRequestFilter,确保每次请求只被过滤一次。
  2. doFilterInternal方法中,它首先检查请求是否是登录请求(通过检查请求路径是否为"/login"以及请求方法是否为"POST")。
  3. 如果是登录请求,它会调用validate方法来校验验证码。
  4. validate方法从请求中获取验证码,然后与会话中存储的验证码进行比对。如果验证码不存在、为空或不匹配,将抛出异常。
  5. 如果验证码校验失败,过滤器会捕获异常,并向响应中写入错误信息(以JSON格式)。
  6. 如果请求不是登录请求,过滤器不会进行验证码校验,直接让请求继续向下执行(通过调用filterChain.doFilter)。
  7. 如果登录请求成功通过验证码校验,代码会继续执行后续的过滤器或处理器。
@Component
public class ValidateCodeFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        // 登陆请求
        if ("/login".equals(httpServletRequest.getServletPath()) &&
                "POST".equalsIgnoreCase(httpServletRequest.getMethod())){
            try {
                validate(httpServletRequest);
            } catch (Exception exception) {
                httpServletResponse.setCharacterEncoding("utf-8");
                httpServletResponse.setContentType("application/json;charset=UTF-8");
                PrintWriter writer = httpServletResponse.getWriter();
                writer.write(JSON.toJSONString(Result.failure(exception.getMessage())));
                writer.flush();
                return;
            }
        }
        // 不是一个登录请求,不做校验 直接通过
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }

    private void validate(HttpServletRequest request) {
        String code = request.getParameter("code");
        if (StringUtils.isBlank(code)){
            throw new RuntimeException("验证码不能为空");
        }
        Object checkCode = request.getSession(false).getAttribute(ConfigConsts.IMAGE_CODE_SESSION);
        if (Objects.isNull(checkCode)) {
            throw new RuntimeException("验证码不存在");
        }
        if (!StringUtils.equalsIgnoreCase(code,checkCode.toString())) {
            throw new RuntimeException("验证码不匹配");
        }
        request.getSession(false).removeAttribute(ConfigConsts.IMAGE_CODE_SESSION);
    }
}
7、集成mysecurity

集成Spring Security的安全配置类,用于Web应用的安全性设置。

  1. 通过@EnableWebSecurity@Configuration注解,启用并配置Spring Security。
  2. 使用@EnableGlobalMethodSecurity(prePostEnabled = true)来启用全局方法级别的安全性,允许使用例如@PreAuthorize@PostAuthorize等注解。
  3. 定义了一个名为MySecurityConfig的配置类,该类继承自WebSecurityConfigurerAdapter,用于定制安全性设置。
  4. 通过@Autowired注入了一个名为validateCodeFilter的验证码过滤器实例。
  5. configure(HttpSecurity http)方法中,对应用的安全性进行了详细配置:
    • 允许所有人访问/loginPage/getImgCode这两个路径,不进行任何安全检查。
    • 对所有其他请求,需要用户进行身份验证(即需要登录后才能访问)。
    • 在用户名和密码验证过滤器之前,添加了一个自定义的验证码过滤器(validateCodeFilter),用于在登录过程中校验验证码。

这段代码的主要目的是增强Web应用的安全性,限制了只有经过身份验证的用户才能访问应用的受保护资源。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
	@Autowired
    private ValidateCodeFilter validateCodeFilter;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 放过
                .antMatchers("/loginPage", "/getImgCode").permitAll()
                .anyRequest().authenticated()
                .and()
                // 过滤登录验证码
                .addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
    }

运行结果如下:

在这里插入图片描述

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

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

相关文章

【TinyALSA全解析(三)】tinyplay、tincap、pcm_open源码解析

tinyplay、tincap、pcm_open源码解析 一、本文的目的二、tinyplay.c源码分析三、tinycap.c源码分析四、pcm.c如何调度到Linux Kernel4.1 pcm_open解析4.1.1 pcm_open的主要流程4.1.2 流程说明4.1.3 调用方法 4.2 pcm_write解析 /*********************************************…

文章改写工具-改写神器

当代社会&#xff0c;信息爆炸&#xff0c;写作已成为人们生活与工作中不可或缺的一环。无论是学术论文、商业报告还是日常沟通&#xff0c;文字的准确表达和精彩呈现是至关重要的。然而&#xff0c;许多人在面对写作时&#xff0c;常常为语言表达、词汇选择而苦恼。为了解决这…

基于OpenCV+YOLOv5实现车辆跟踪与计数(附源码)

导 读 本文主要介绍基于OpenCVYOLOv5实现车辆跟踪与计数的应用&#xff0c;并给出源码。 资源下载 基础代码和视频下载地址&#xff1a; https://github.com/freedomwebtech/win11vehiclecount main.py代码:​​​​​​​ import cv2import torchimport numpy as npfrom tr…

Dockerfile讲解

Dockerfile 1. 构建过程解析2. Dockerfile常用保留字指令3. 案例3.1. 自定义镜像mycentosjava83.2. 虚悬镜像 4. Docker微服务实战 dockerfile是用来构建docker镜像的文本文件&#xff0c;是由一条条构建镜像所需的指令和参数构成的脚本。 dockerfile定义了进程需要的一切东西&…

hdlbits系列verilog解答(Exams/m2014 q4e)-46

文章目录 一、问题描述二、verilog源码三、仿真结果 一、问题描述 实现以下电路&#xff1a; 二、verilog源码 module top_module (input in1,input in2,output out);assign out ~(in1 | in2);endmodule三、仿真结果 转载请注明出处&#xff01;

JOSEF 综合继电器 HJZZ-32/2 AC220V 合闸延时整定0.02-9.99S

系列型号&#xff1a; HJZZ-91分闸、合闸、电源监视综合装置&#xff1b; HJZZ-92/1分闸、合闸、电源监视综合装置&#xff1b; HJZZ-92/2分闸、合闸、电源监视综合装置&#xff1b; HJZZ-92/2A分闸、合闸、电源监视综合装置&#xff1b; HJZZ-92/3分闸、合闸、电源监视综…

Gitee上传代码教程

1. 本地安装git 官网下载太慢&#xff0c;我们也可以使用淘宝镜像下载&#xff1a;CNPM Binaries Mirror 安装成功以后电脑会有Git Bush标识&#xff0c;空白处右键也可查看。 2. 注册gitee账号&#xff08;略&#xff09; 3. 创建远程仓库 4. 上传代码 4.1 在项目文件目录…

【教学类-06-10】20231126 X-Y数字分合-分-下空左

结果展示&#xff1a; 背景需求&#xff1a; 数字分合&#xff0c;这一次空在左侧 代码展示&#xff1a; X-Y 之间的分合题-分-空在右侧 时间&#xff1a;2023年11月26日 21:46 作者&#xff1a;阿夏 import random from win32com.client import constants,gencache from win3…

python之静态服务器程序开发

文章目录 Python静态Web服务器开发Web静态服务器初识搭建Python自带的静态Web服务器静态Web服务器返回固定页面数据静态Web服务器返回指定页面数据静态Web服务器多任务版静态Web服务器面向对象开发静态Web服务器命令行启动动态绑定端口号 Python静态Web服务器开发 Web静态服务…

Web3.0时代:区块链DAPP将如何颠覆传统模式

小编介绍&#xff1a;10年专注商业模式设计及软件开发&#xff0c;擅长企业生态商业模式&#xff0c;商业零售会员增长裂变模式策划、商业闭环模式设计及方案落地&#xff1b;扶持10余个电商平台做到营收过千万&#xff0c;数百个平台达到百万会员&#xff0c;欢迎咨询。 随着…

基于DSP/SOC音乐灯效系统设计方法

音乐灯效系统设计方法 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送语音信号处理降噪算法,蓝牙耳机音频,DSP音频项目核心开发资料, 三种方法: (1)MIC 采集音乐信号变化,(2)直接获取SPK 模拟音频…

使用char.js 柱形方式显示 一年12个月的最高气温与最低气温

<!DOCTYPE html> <html> <head><title>气温图表</title><script src"https://cdn.jsdelivr.net/npm/chart.js"></script><style>#myChart{width:800px;height: 400px;}</style> </head> <body>&l…

【Linux】:信号在内核里的处理

信号的发送和保存 一.内核中的信号处理二.信号集操作函数1.一些信号函数2.sigprocmask3.sigpending4.写代码 三.信号在什么时候处理的四.再谈地址空间 一.内核中的信号处理 1.实际执行信号的处理动作称为信号递达(Delivery )2.信号从产生到递达之间的状态,称为信号未决(Pending…

通义灵码,你的智能编码助手,免费公测啦!

目录 ​编辑 1、介绍 2、安装 3、功能介绍 行/函数级实时续写 自然语言生成代码 单元测试生成 代码注释生成 代码解释 研发智能问答 多编程语言、多编辑器全方位支持 4、视频 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家…

QT Day01 qt概述,创建项目,窗口属性,按钮,信号与槽

1.qt概述 1.什么是qt Qt 是一个跨平台的 C 图形用户界面应用程序框架。它为应用程序开发者提供建立艺 术级图形界面所需的所有功能。它是完全面向对象的&#xff0c;很容易扩展&#xff0c;并且允许真正的组 件编程。 2.支持的平台 Windows – XP 、 Vista 、 Win7 、 Win8…

博捷芯打破半导体切割划片设备技术垄断,国产产业链实现高端突破

近日&#xff0c;国内半导体产业传来喜讯&#xff0c;博捷芯成功实现批量供货半导体切割划片设备&#xff0c;打破国外企业在该领域的长期技术垄断&#xff0c;为国产半导体产业链在高端切割划片设备领域实现重大突破。 自上世纪90年代以来&#xff0c;由于国外企业的技术封锁和…

通俗易懂的spring Cloud;业务场景介绍 二、Spring Cloud核心组件:Eureka 、Feign、Ribbon、Hystrix、zuul

文章目录 通俗易懂的spring Cloud一、业务场景介绍二、Spring Cloud核心组件&#xff1a;Eureka三、Spring Cloud核心组件&#xff1a;Feign四、Spring Cloud核心组件&#xff1a;Ribbon五、Spring Cloud核心组件&#xff1a;Hystrix六、Spring Cloud核心组件&#xff1a;Zuul七…

vivado产生报告阅读分析25-复杂性报告

对于顶层设计和 / 或包含 1000 个以上叶节点单元的层级单元 &#xff0c; 复杂性报告会显示每个叶节点单元类型的“ Rent Exponent” &#xff08; Rent 指数 &#xff09; 、“ Average Fanout ” &#xff08; 平均扇出 &#xff09; 和分布。 Rent 指数是指在使用最小割 …

Linux中tar命令的几个高级用法

在Linux世界中&#xff0c;Tar命令是一把解密归档世界的魔法工具。无论是打包、压缩还是解压&#xff0c;Tar命令都能胜任。本文将生动地介绍Tar命令的基本用法&#xff0c;并深入探讨五个常用选项&#xff0c;帮助读者在Linux系统中灵活运用这个强大的工具。 一、命令概述 Ta…

西北大学计算机844考研-23年计网计算题详细解析

西北大学计算机844考研-23年计网计算题详细解析 1.计算无传输差错状态下停止—等待ARQ协议效率,电磁波传播速率为2*10^8m/s&#xff0c;链路长为2000m&#xff0c;帧长度为1000比特&#xff0c;计算传输速率10kbps及10Mbps时的协议效率&#xff08;即信道利用率&#xff09; …