当前位置: 首页 > 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;并将其关联…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

基于Java+VUE+MariaDB实现(Web)仿小米商城

仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意&#xff1a;运行前…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...