【SpringSecurity】八、集成图片验证码
文章目录
- 1、生成图片验证码
- 2、创建验证码过滤器
- 3、将过滤器加入SpringSecurity过滤链
- 4、修改登录页
SpringSecurity是通过过滤器链来完成的,接下来的验证码,可以尝试创建一个过滤器放到Security的过滤器链中,在自定义的过滤器中比较验证码。
1、生成图片验证码
引入hutool依赖,用于生成验证码。(这个单词怎么读?糊涂?)
<!--引入hutool-->
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.3.9</version>
</dependency>
写个用于生成验证码的接口:
//HttpServletRequest和HttpServletResponse对象使用自动注入或者写在controller方法的形参都行
@Controller
@Slf4j
public class CaptchaController {@GetMapping("/code/image")public void getCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {//创建一个验证码CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(200, 100, 2, 20);//获取生成的图片二维码中的值,并放到session中String captchaCode=circleCaptcha.getCode();log.info("生成的验证码为:{}",captchaCode);request.getSession().setAttribute("LOGIN_CAPTCHA_CODE",captchaCode);//将图片写到响应流中,参数一是图片。参数二是图片格式,参数三是响应流ImageIO.write(circleCaptcha.getImage(),"JPEG",response.getOutputStream());}
}
此时,调用这个接口会在响应里返回一个图片。调用下接口看看效果:

2、创建验证码过滤器
很明显,校验验证码要先于校验用户名密码,验证码都不对,就不用往下验证用户名和密码了。新建自定义过滤器类ValidateCodeFilter,继承抽象类OncePerRequestFilter 。右键看下继承关系:

可以看到最终是实现了Filter接口。但这里别直接实现Filter,继承OncePerRequestFilter,里面的好多东西直接用,能省一点是一点。过滤器的实现思路为:
- 从前端获取验证码
- 从session中获取验证码(生成验证码的时候塞session里了)
- 判断是否相等
@Component
@Slf4j
public class ValidateCodeFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {//因为最后是Filter接口,所以所有请求都过这个过滤器//这里要先判断接口是不是登录接口,不是就别对比session和前端传来的验证码了String requestURI = request.getRequestURI(); //URI即去掉IP、PORT那串log.info("请求的URI为:{}", requestURI);if (!requestURI.equals("/login/doLogin")) {doFilter(request, response, filterChain); //不是登录接口直接放行} else {validateCode(request, response,filterChain); //是登录接口则校验}}private void validateCode(HttpServletRequest request, HttpServletResponse response,FilterChain filterChain) throws IOException, ServletException {String enterCaptchaCode = request.getParameter("code"); //从请求中拿传过来的验证码的值(dto好些)HttpSession session = request.getSession();String captchaCodeInSession = (String) session.getAttribute("LOGIN_CAPTCHA_CODE"); //保存在session中的验证码log.info("用户输入的验证码为:{},session中的验证码为:{}",enterCaptchaCode,captchaCodeInSession);//移除session中之前可能存在的错误信息session.removeAttribute("captchaCodeErrorMsg");if (!StringUtils.hasText(captchaCodeInSession)) {session.removeAttribute("LOGIN_CAPTCHA_CODE");}if (!StringUtils.hasText(enterCaptchaCode) || !StringUtils.hasText(captchaCodeInSession) || !enterCaptchaCode.equalsIgnoreCase(captchaCodeInSession)) {//说明验证码不正确,返回登陆页面session.setAttribute("captchaCodeErrorMsg", "验证码不正确");//验证失败,重定向到登录页面response.sendRedirect("/login/toLogin");}else{filterChain.doFilter(request,response); //验证成功,放行}}
}
关于requset.getParameter("code")
关于在controller中接收前端数据的方式:
关于直接在请求中获取参数的建议:
3、将过滤器加入SpringSecurity过滤链
修改WebSecurityConfig:
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Resourceprivate ValidateCodeFilter validateCodeFilter; //自动注入我定义的验证码过滤器@Override/*** Security的http请求配置** @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {//设置登陆方式http.formLogin()//使用用户名和密码的登陆方式.usernameParameter("uname") //页面表单的用户名的name.passwordParameter("pwd")//页面表单的密码的name.loginPage("/login/toLogin") //自己定义登陆页面的地址.loginProcessingUrl("/login/doLogin")//配置登陆的url.successForwardUrl("/index/toIndex") //登陆成功跳转的页面.failureForwardUrl("/login/toLogin")//登陆失败跳转的页面.permitAll();//配置退出方式http.logout().logoutUrl("/logout").logoutSuccessUrl("/login/toLogin").permitAll();//配置路径拦截 的url的匹配规则http.authorizeRequests().antMatchers("/code/image").permitAll()//任何路径要求必须认证之后才能访问.anyRequest().authenticated();// 禁用csrf跨站请求,注意不要写错了http.csrf().disable();// 配置登录之前添加一个验证码的过滤器 http.addFilterBefore(validateCodeFilter,UsernamePasswordAuthenticationFilter.class);}/*** 资源服务匹配放行【静态资源文件】** @param web* @throws Exception*/// @Override//public void configure(WebSecurity web) throws Exception {// web.ignoring().mvcMatchers("/resources/**");//}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}
以上注意两点,一是别忘了放行生成二维码的接口,这个不需要登录鉴权。
http.authorizeRequests().antMatchers("/code/image").permitAll()//任何路径要求必须认证之后才能访问.anyRequest().authenticated();
而是在用户名密码验证过滤器前加一个自定义的验证码过滤器,addFilter方法:
http.addFilterBefore(validateCodeFilter,UsernamePasswordAuthenticationFilter.class);
4、修改登录页
修改login.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>用户登陆</title>
</head>
<body>
<h2>登录页面</h2>
<!--${param.error}这个如果有值,就显示帐号或密码错误-->
<h4 th:if="${param.error}" style="color: #FF0000;">帐号或密码错误,请重新输入</h4>
<form action="/login/doLogin" method="post"><table><tr><td>用户名:</td><td><input type="text" name="uname" value="zhangsan"></td></tr><tr><td>密码:</td><td><input type="password" name="pwd"></td></tr><tr><td>验证码:</td><td><input type="text" name="code"> <img src="/code/image" style="height:33px;cursor:pointer;" onclick="this.src=this.src"><span th:text="${session.captchaCodeErrorMsg}" style="color: #FF0000;" >username</span></td></tr><tr><td colspan="2"><button type="submit">登录</button></td></tr></table>
</form>
</body>
效果:

相关文章:
【SpringSecurity】八、集成图片验证码
文章目录 1、生成图片验证码2、创建验证码过滤器3、将过滤器加入SpringSecurity过滤链4、修改登录页 SpringSecurity是通过过滤器链来完成的,接下来的验证码,可以尝试创建一个过滤器放到Security的过滤器链中,在自定义的过滤器中比较验证码。…...
【本地代码问题】启动程序,报错:java.lang.IllegalArgumentException: No selectors
启动程序的时候报错了 问题怎么出现的解决方式,注释掉jetty的内容,回归tomcat的使用 问题怎么出现的 我本地启动程序的时候报错了:报的是这个错误,可能和容器的选择有关吧 解决方式,注释掉jetty的内容,回…...
手写RPC框架--4.服务注册
RPC框架-Gitee代码(麻烦点个Starred, 支持一下吧) RPC框架-GitHub代码(麻烦点个Starred, 支持一下吧) 服务注册 服务注册a.添加服务节点和主机节点b.抽象注册中心c.本地服务列表 服务注册 a.添加服务节点和主机节点 主要完成服务注册和发现的功能,其具体流程如下&…...
oracle 解锁表
操作的前提 用 sys 用户 以 SYSDBA 角色登录 第一种解锁方式 1.查询被锁的表 select object_name,machine,s.sid,s.serial# from v$locked_object l,dba_objects o ,v$session s where l.object_id o.object_id and l.session_ids.sid;2.查询那个session引起表被锁 sele…...
使用Dbeaver连接GaussDB
1.下载DBeaver,官网地址 2.安装软件,打开软件,点击数据库->驱动管理器,具体操作如下图: 3、选择新建后进行参数设置,如下图: 具体参数如下图 驱动名称: GS #随便定义 驱动类型&#…...
WSL使用技巧 / 虚拟机对比
WSL使用技巧 / 虚拟机对比 前言虚拟机比较VMware使用技巧WSL使用技巧官方文档工具安装WSL基本命令运行命令关闭卸载磁盘管理导入导出指定安装路径 前言 本文介绍了VMware和WSL的区别,并详细介绍了WSL的使用方法和技巧。 虚拟机比较 VMware 比较灵活,拥…...
vuex_cart案例
json-server使用 在目录下新建db文件夹>里面新建index.json index.json {"cart": [{"id": 100001,"name": "低帮城市休闲户外鞋天然牛皮COOLMAX纤维","price": 128,"count": 6,"thumb": "http…...
Linux系统的安装
文章目录 1 Linux介绍1.1 Linux是什么1.2 Linux的特点1.3 Linux的应用1.4 Linux的发行版本1.5 Linux的Shell 2 Linux安装2.1 安装方式2.2 什么是VMware2.3 VMware主要功能2.4 什么是CentOS2.5 VMware与CentOS与Linux的关系2.6 VMware安装CentOS的步骤 1 Linux介绍 1.1 Linux是…...
微服务设计和高并发实践
文章目录 1、微服务的设计原则1.1、服务拆分方法1.2、微服务的设计原则1.3、微服务架构 2、高并发系统的一些优化经验2.1、提高性能2.1.1、数据库优化2.1.2、使用缓存2.1.3、服务调用优化2.1.4、动静分离2.1.5、数据库读写分离 2.2、服务高可用2.2.1、限流和服务降级2.2.2、隔离…...
2023年高教社杯数学建模思路 - 案例:粒子群算法
文章目录 1 什么是粒子群算法?2 举个例子3 还是一个例子算法流程算法实现建模资料 # 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 什么是粒子群算法? 粒子群算法(Pa…...
Tomcat 集群介绍
一.Tomcat 集群介绍 在实际生产环境中,单台 Tomcat 服务器的负载能力或者说并发能力在四五百左右。大 部分情况下随着业务增长,访问量的增加(并发量不止四五百),单台 Tomcat 服务器是 无法承受的。这时就需要将多台 Tomcat 服务器组织起来&a…...
Windows右键添加用 IDEA 打开
1.安装IDEA时 安装时会有个选项来添加,如下: 勾选即可 2.修改注册表 安装时未勾选,可以把下面代码中程序路径改为自己的,保存为对应的 idea.reg文件,双击即可 Windows Registry Editor Version 5.00[HKEY_CLASSES…...
Golang 中return和defer执行先后顺序
先给出最终结论: 执行return语句 -> 执行defer函数 -> 函数返回 这里可能会有一个疑问, 执行return语句和函数返回难道不是一回事? Golang语言中函数的return不是原子操作,而是分为了两步: 返回值赋值真正函数返回 Gol…...
业务数据模拟/采集
业务数据模拟/采集 2.2 业务数据模拟 2.2.1 连接MySQL 通过MySQL可视化客户端连接数据库。2.2.2 建表语句 1)通过SQLyog创建数据库2)设置数据库名称为gmall,编码为utf-8,排序规则为utf8_general_ci3)导入数据库结构脚本…...
qt day 5
实现局域网的网络聊天室功能 1>服务器代码 --------------------------------------------------------------- widget.h --------------------------------------------------------------- #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMes…...
Java设计模式之适配器模式
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。 这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子࿰…...
每天一个工业通信协议(3)2023.8.29 (DAP接口)
文章目录 参考文献1.DAP接口介绍2.DAP接口的2/3pin3.一种DAP接口方案应用的说明,通过两步初始化把JTAG接口变成DAP接口使用4.DAP接口的协议4.1 DAP电报的分类(只用JTAG类电报)4.2 电报格式4.3 DAP有限状态机参考文献 李婧. DAP模块验证组件系统级开发和实现[D]. 陕西:西安电…...
如何将Word转成PDF?试一下这个转换方法
Word转成PDF是现代办公中常见的需求,它可以确保文件的格式和内容在不同平台上保持一致,并且更加方便共享和打印。在这个数字化时代,我们经常需要将Word文档转换为PDF格式,无论是个人用户还是商务用户都会遇到这样的需求。那么如何…...
成都睿趣科技:现在开一家抖音小店还来得及吗
随着社交媒体的迅猛发展,抖音已经成为了一个全球范围内广受欢迎的社交平台。在这个短视频应用上,人们分享着各种各样的内容,从搞笑段子到美食教程,再到时尚搭配和手工艺品制作。随着用户数量的不断增长,很多人都在思考…...
原型链中:为什么Function.proto==Function.prototype?
背景: 在 JavaScript 中,每个函数(包括构造函数)都是一个对象,而对象都有一个 __proto__ 属性,指向它们的原型。当你创建一个函数时,JavaScript 引擎会自动为该函数创建一个原型对象,并将其关联…...
Spring IoC 与 DI 核心详解 —— 基于 XML 配置:Bean 创建、依赖注入与生命周期全解析(Spring系列1)
在 Java 企业级开发中,Spring 框架凭借其强大的 IoC(控制反转) 与 DI(依赖注入) 能力,成为了事实上的标准。本文将带你从最原始的 XML 配置开始,逐步过渡到纯注解开发,并深入剖析 Io…...
百考通:AI精准赋能任务书生成,让科研与项目启动更高效
在学术研究、课程设计与项目开发的起步阶段,一份规范、清晰的任务书是指引方向的核心纲领。但从选题构思到内容撰写,往往让研究者与学生陷入困境:选题迷茫、逻辑混乱、要求表述模糊,严重拖慢项目推进节奏。百考通(http…...
电子元器件失效分析与预防实战指南
1. 电子元器件失效的底层逻辑剖析 电子元器件失效的本质是材料特性、环境应力与时间因素共同作用的结果。作为一名硬件工程师,我处理过数百例元器件失效案例,发现失效模式往往遵循"应力-损伤-失效"的因果链。理解这个链条,才能从根…...
STM32电位器驱动库:轻量级ADC封装与中值滤波实现
1. 项目概述MentorBit-Potenciometro 是一款专为 MentorBit 系统设计的轻量级电位器(Potentiometer)模块驱动库,面向 STM32 平台(典型为 STM32F4/F7/H7 系列)的嵌入式固件开发。该库并非通用 ADC 抽象层,而…...
JAE日本航空电子推出满足汽车市场小型防水最新需求的MX80系列连接器
随着汽车电子化和高功能化的演进,每辆汽车所搭载的电子设备数量逐年增加。为了在有限安装空间内集成更多的功能,车载用电子零部件必然要求进一步小型化,高功能化。同时由于连接各设备之间的布线空间也在缩小,因此开发小型化&#…...
SEO的黑帽和白帽技术分别是什么_如何查询网站的SEO指标和排名数据
SEO的黑帽和白帽技术分别是什么_如何查询网站的SEO指标和排名数据 在当今的互联网时代,搜索引擎优化(SEO)是提升网站流量和可见度的关键。SEO有许多技术和方法,其中包括白帽技术和黑帽技术。了解这些技术不仅有助于提升网站的搜索…...
解决WPS标题编号不从‘一‘开始的烦恼:新手必看避坑指南
WPS标题编号异常全解析:从问题根源到高阶应用技巧 刚接触WPS文字处理的新手们,经常会遇到一个令人困惑的现象——文档中的标题编号莫名其妙地从"二"或"三"开始,而不是预期的"一"。这种情况不仅影响文档美观&am…...
Vue表单生成器深度解析:3个维度重塑你的表单开发体验
Vue表单生成器深度解析:3个维度重塑你的表单开发体验 【免费下载链接】vue-form-generator :clipboard: A schema-based form generator component for Vue.js 项目地址: https://gitcode.com/gh_mirrors/vu/vue-form-generator 在当今快速迭代的前端开发中&…...
DeepFaceLive实时面部交换技术完全教程
DeepFaceLive实时面部交换技术完全教程 还在为视频会议和直播效果发愁吗?想不想在下次Zoom会议中突然变身成你喜欢的明星?DeepFaceLive这款神奇的工具能让你的面部特效梦想成真!今天我们就来聊聊这个让无数内容创作者痴迷的实时面部交换技术…...
PyCharm配置PySide6工具链避坑指南:解决虚拟环境路径、命令报错那些事儿
PyCharm配置PySide6工具链避坑指南:解决虚拟环境路径、命令报错那些事儿 刚接触PySide6开发的朋友,十有八九会在PyCharm配置Designer、UIC和RCC工具时踩坑。明明照着教程一步步操作,却总是遇到"程序不存在"、"命令执行错误&qu…...



