【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 引擎会自动为该函数创建一个原型对象,并将其关联…...

原生js实现轮播图及无缝滚动
我这里主要说轮播图和无缝滚动的实现思路,就采用最简单的轮播图了,当然实现的思路有很多种,我这也只是其中一种。 简单轮播图的大概结构是这样的,中间是图片,二边是箭头可以用来切换图片,下面的小圆点也可以…...

MP中的字段还可以利用函数来查询拼接sql
//根据value查询GetMapping("getTest")public List<HashMap> getTest() {QueryWrapper<TTest> queryWrapper new QueryWrapper<>();queryWrapper.eq("substr(name,1,2)","99999");List<TTest> list1 testService.list…...

【python爬虫】中央气象局预报—静态网页图像爬取练习
静态网页爬取练习 中央气象局预报简介前期准备步骤Python爬取每日预报结果—以降水为例 中央气象局预报简介 中央气象台是中国气象局(中央气象台)发布的七天降水预报页面。这个页面提供了未来一周内各地区的降水预报情况,帮助人们了解即将到来…...

数字孪生城市总体架构进一步迭代更新
经过五年来发展,数字孪生城市基本形成“三横四纵”的总体架构,“三横”为新型基础设施、智能运行中枢、孪生应用体系,“四纵”为组织保障体系、标准规范体系、网络安全防线、运营保障体系,具体如下。 数字孪生城市总体架构-来源&a…...

通过 Jetbrains GateWay实现Remote Development
本次环境准备 环境准备:win10、一台安装有树莓派系统的树莓派(也可以是其他的服务器) 第一步:通过官网下载JetBrains Gateway 官网地址:https://www.jetbrains.com/remote-development/gateway/ 第二步:安装…...

springboot 集成 lucene
简介 数据每分钟产生200条,使用mysql储存。目前有数据超过700M。按照日期查询,按月查询包含每次超过20w条以上,时间比较长。计划使用lucene优化查询,不适用es是因为项目较小,没有更富裕的资源。 基本步骤 引入依赖。…...

Android开机动画
Android开机动画 1、BootLoader开机图片2、Kernel开机图片3、系统启动时(BootAnimation)动画3.1 bootanimation.zip位置3.2 bootanimation启动3.3 SurfaceFlinger启动bootanimation3.4 播放开机动画playAnimation3.6 开机动画退出检测3.7 简易时序图 4、…...

vue中使用wow.js
一、安装 npm install wowjs --save-dev 二、main中引入 animate.css会自动安装 因为wow.js在animate.css基础上 main.js中引入animate.css import "animate.css" 三、 页面使用 有两种引入使用方式:1. import {WOW} from wowjs mounted() { n…...

网站edge -- 油猴 -> IDM
一、百度网盘限速 未解决 软件:IDM 安装路径: 1.1如果:edge 出问题打不开其他网站, 解决方法: 以管理员的身份,右击载这个软件,就好了 1.2使用这个软件 应该是右击这个软件 以管理员的身…...

Android片段
如果你希望应用根据不同的环境有不同的外观和行为,这种情况下就需要片段,片段是可以由不同活动重用的模块化代码组件。 片段(Fragment)是活动(Activity)的一种模块化部分,表示活动中的行为或界面…...