当前位置: 首页 > news >正文

【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是通过过滤器链来完成的&#xff0c;接下来的验证码&#xff0c;可以尝试创建一个过滤器放到Security的过滤器链中&#xff0c;在自定义的过滤器中比较验证码。…...

【本地代码问题】启动程序,报错:java.lang.IllegalArgumentException: No selectors

启动程序的时候报错了 问题怎么出现的解决方式&#xff0c;注释掉jetty的内容&#xff0c;回归tomcat的使用 问题怎么出现的 我本地启动程序的时候报错了&#xff1a;报的是这个错误&#xff0c;可能和容器的选择有关吧 解决方式&#xff0c;注释掉jetty的内容&#xff0c;回…...

手写RPC框架--4.服务注册

RPC框架-Gitee代码(麻烦点个Starred, 支持一下吧) RPC框架-GitHub代码(麻烦点个Starred, 支持一下吧) 服务注册 服务注册a.添加服务节点和主机节点b.抽象注册中心c.本地服务列表 服务注册 a.添加服务节点和主机节点 主要完成服务注册和发现的功能&#xff0c;其具体流程如下&…...

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&#xff0c;官网地址 2.安装软件&#xff0c;打开软件&#xff0c;点击数据库->驱动管理器&#xff0c;具体操作如下图&#xff1a; 3、选择新建后进行参数设置&#xff0c;如下图&#xff1a; 具体参数如下图 驱动名称: GS #随便定义 驱动类型&#…...

WSL使用技巧 / 虚拟机对比

WSL使用技巧 / 虚拟机对比 前言虚拟机比较VMware使用技巧WSL使用技巧官方文档工具安装WSL基本命令运行命令关闭卸载磁盘管理导入导出指定安装路径 前言 本文介绍了VMware和WSL的区别&#xff0c;并详细介绍了WSL的使用方法和技巧。 虚拟机比较 VMware 比较灵活&#xff0c;拥…...

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 什么是粒子群算法&#xff1f;2 举个例子3 还是一个例子算法流程算法实现建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是粒子群算法&#xff1f; 粒子群算法&#xff08;Pa…...

Tomcat 集群介绍

一.Tomcat 集群介绍 在实际生产环境中&#xff0c;单台 Tomcat 服务器的负载能力或者说并发能力在四五百左右。大 部分情况下随着业务增长&#xff0c;访问量的增加(并发量不止四五百)&#xff0c;单台 Tomcat 服务器是 无法承受的。这时就需要将多台 Tomcat 服务器组织起来&a…...

Windows右键添加用 IDEA 打开

1.安装IDEA时 安装时会有个选项来添加&#xff0c;如下&#xff1a; 勾选即可 2.修改注册表 安装时未勾选&#xff0c;可以把下面代码中程序路径改为自己的&#xff0c;保存为对应的 idea.reg文件&#xff0c;双击即可 Windows Registry Editor Version 5.00[HKEY_CLASSES…...

Golang 中return和defer执行先后顺序

先给出最终结论&#xff1a; 执行return语句 -> 执行defer函数 -> 函数返回 这里可能会有一个疑问&#xff0c; 执行return语句和函数返回难道不是一回事? Golang语言中函数的return不是原子操作&#xff0c;而是分为了两步&#xff1a; 返回值赋值真正函数返回 Gol…...

业务数据模拟/采集

业务数据模拟/采集 2.2 业务数据模拟 2.2.1 连接MySQL 通过MySQL可视化客户端连接数据库。2.2.2 建表语句 1&#xff09;通过SQLyog创建数据库2&#xff09;设置数据库名称为gmall&#xff0c;编码为utf-8&#xff0c;排序规则为utf8_general_ci3&#xff09;导入数据库结构脚本…...

qt day 5

实现局域网的网络聊天室功能 1>服务器代码 --------------------------------------------------------------- widget.h --------------------------------------------------------------- #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMes…...

Java设计模式之适配器模式

适配器模式&#xff08;Adapter Pattern&#xff09;是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式&#xff0c;它结合了两个独立接口的功能。 这种模式涉及到一个单一的类&#xff0c;该类负责加入独立的或不兼容的接口功能。举个真实的例子&#xff0…...

每天一个工业通信协议(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是现代办公中常见的需求&#xff0c;它可以确保文件的格式和内容在不同平台上保持一致&#xff0c;并且更加方便共享和打印。在这个数字化时代&#xff0c;我们经常需要将Word文档转换为PDF格式&#xff0c;无论是个人用户还是商务用户都会遇到这样的需求。那么如何…...

成都睿趣科技:现在开一家抖音小店还来得及吗

随着社交媒体的迅猛发展&#xff0c;抖音已经成为了一个全球范围内广受欢迎的社交平台。在这个短视频应用上&#xff0c;人们分享着各种各样的内容&#xff0c;从搞笑段子到美食教程&#xff0c;再到时尚搭配和手工艺品制作。随着用户数量的不断增长&#xff0c;很多人都在思考…...

原型链中:为什么Function.proto==Function.prototype?

背景: 在 JavaScript 中&#xff0c;每个函数&#xff08;包括构造函数&#xff09;都是一个对象&#xff0c;而对象都有一个 __proto__ 属性&#xff0c;指向它们的原型。当你创建一个函数时&#xff0c;JavaScript 引擎会自动为该函数创建一个原型对象&#xff0c;并将其关联…...

Spring IoC 与 DI 核心详解 —— 基于 XML 配置:Bean 创建、依赖注入与生命周期全解析(Spring系列1)

在 Java 企业级开发中&#xff0c;Spring 框架凭借其强大的 IoC&#xff08;控制反转&#xff09; 与 DI&#xff08;依赖注入&#xff09; 能力&#xff0c;成为了事实上的标准。本文将带你从最原始的 XML 配置开始&#xff0c;逐步过渡到纯注解开发&#xff0c;并深入剖析 Io…...

百考通:AI精准赋能任务书生成,让科研与项目启动更高效

在学术研究、课程设计与项目开发的起步阶段&#xff0c;一份规范、清晰的任务书是指引方向的核心纲领。但从选题构思到内容撰写&#xff0c;往往让研究者与学生陷入困境&#xff1a;选题迷茫、逻辑混乱、要求表述模糊&#xff0c;严重拖慢项目推进节奏。百考通&#xff08;http…...

电子元器件失效分析与预防实战指南

1. 电子元器件失效的底层逻辑剖析 电子元器件失效的本质是材料特性、环境应力与时间因素共同作用的结果。作为一名硬件工程师&#xff0c;我处理过数百例元器件失效案例&#xff0c;发现失效模式往往遵循"应力-损伤-失效"的因果链。理解这个链条&#xff0c;才能从根…...

STM32电位器驱动库:轻量级ADC封装与中值滤波实现

1. 项目概述MentorBit-Potenciometro 是一款专为 MentorBit 系统设计的轻量级电位器&#xff08;Potentiometer&#xff09;模块驱动库&#xff0c;面向 STM32 平台&#xff08;典型为 STM32F4/F7/H7 系列&#xff09;的嵌入式固件开发。该库并非通用 ADC 抽象层&#xff0c;而…...

JAE日本航空电子推出满足汽车市场小型防水最新需求的MX80系列连接器

随着汽车电子化和高功能化的演进&#xff0c;每辆汽车所搭载的电子设备数量逐年增加。为了在有限安装空间内集成更多的功能&#xff0c;车载用电子零部件必然要求进一步小型化&#xff0c;高功能化。同时由于连接各设备之间的布线空间也在缩小&#xff0c;因此开发小型化&#…...

SEO的黑帽和白帽技术分别是什么_如何查询网站的SEO指标和排名数据

SEO的黑帽和白帽技术分别是什么_如何查询网站的SEO指标和排名数据 在当今的互联网时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;是提升网站流量和可见度的关键。SEO有许多技术和方法&#xff0c;其中包括白帽技术和黑帽技术。了解这些技术不仅有助于提升网站的搜索…...

解决WPS标题编号不从‘一‘开始的烦恼:新手必看避坑指南

WPS标题编号异常全解析&#xff1a;从问题根源到高阶应用技巧 刚接触WPS文字处理的新手们&#xff0c;经常会遇到一个令人困惑的现象——文档中的标题编号莫名其妙地从"二"或"三"开始&#xff0c;而不是预期的"一"。这种情况不仅影响文档美观&am…...

Vue表单生成器深度解析:3个维度重塑你的表单开发体验

Vue表单生成器深度解析&#xff1a;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实时面部交换技术完全教程 还在为视频会议和直播效果发愁吗&#xff1f;想不想在下次Zoom会议中突然变身成你喜欢的明星&#xff1f;DeepFaceLive这款神奇的工具能让你的面部特效梦想成真&#xff01;今天我们就来聊聊这个让无数内容创作者痴迷的实时面部交换技术…...

PyCharm配置PySide6工具链避坑指南:解决虚拟环境路径、命令报错那些事儿

PyCharm配置PySide6工具链避坑指南&#xff1a;解决虚拟环境路径、命令报错那些事儿 刚接触PySide6开发的朋友&#xff0c;十有八九会在PyCharm配置Designer、UIC和RCC工具时踩坑。明明照着教程一步步操作&#xff0c;却总是遇到"程序不存在"、"命令执行错误&qu…...