【SpringSecurity】八、集成图片验证码

news2024/11/18 10:58:17

文章目录

  • 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 {
    @Override
    protected 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 {


    @Resource
    private ValidateCodeFilter validateCodeFilter;  //自动注入我定义的验证码过滤器

    @Override
    /**
     * Security的http请求配置
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected 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/**");
    //}


    @Bean
    public 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>

效果:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux系统下Web文件系统搭建

背景 为了方便和协作者共享文件和方便文件统一管理及下载&#xff0c;比如分享API文档&#xff0c;因此搭建一个简易的基于Apache服务的Web文件系统&#xff0c;使用浏览器进行文件访问及下载。 部署Apache服务器 本文的linux开发环境是Ubuntu 18.04 安装 sudo apt instal…

Collections和CollectionUtils集合操作

0.引入依赖 <dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.4</version> </dependency> 一.Collections用法&#xff1a; 01、排序操作 reverse(List list)…

C++面试题(丝)-计算机网络部分(1)

目录 1计算机网络 53 简述epoll和select的区别&#xff0c;epoll为什么高效&#xff1f; 54 说说多路IO复用技术有哪些&#xff0c;区别是什么&#xff1f; 55 简述socket中select&#xff0c;epoll的使用场景和区别&#xff0c;epoll水平触发与边缘触发的区别&#xff1f;…

学术加油站|基于端到端性能的学习型基数估计器综合测评

编者按 本文系东北大学李俊虎所著&#xff0c;也是「 OceanBase 学术加油站」系列第 11 篇内容。 「李俊虎&#xff1a;东北大学计算机科学与工程学院在读硕士生&#xff0c;课题方向为数据库查询优化&#xff0c;致力于应用 AI 技术改进传统基数估计器&#xff0c;令数据库选…

第五章 树与二叉树 五、哈夫曼树(定义与构造方法),哈夫曼编码

一、带权路径长度 1.结点的权:有某种现实含义的数值&#xff08;如:表示结点的重要性等&#xff09; 2.结点的带权路径长度:从树的根到该结点的路径长度(经过的边数&#xff09;与该结点上权值的乘积。 3.树的带权路径长度:树中所有叶结点的带权路径长度之和。&#xff08;W…

740914L、740928LD、740912D插头式比例控制线圈放大器

740912、740912D、740912L、740912LD 740914、740914D、740914L、740914LD 740924、740924D、740924L、740924LD 740928、740928D、740928L、740928LD 770212、770214、770214N、770223 一般情况下选用的线圈&#xff0c;在工作的工程中&#xff0c;一般是不可能发生问题的…

关于PMP!被问到发疯的10个问题!!

最近很多人都在问我PMP证书相关的几个问题&#xff0c;我大致整理出来&#xff0c;统一回答。 1&#xff09;这是个什么证书&#xff1f;2&#xff09;到底有什么用&#xff1f;3&#xff09;考下来需要多少钱&#xff1f;4&#xff09;能不能不报班自己学&#xff1f;5&#…

【HarmonyOS】一文教你如何使用低代码平台网格布局动态加载数据

【关键字】 低代码平台、AGC、API6、网格布局、数据模型 【写在前面】 正式开工之前&#xff0c;先来说一下今天要实现的内容&#xff0c;今天会实现一个网格布局的展示&#xff0c;我会创建一个数据模型&#xff0c;然后网格列表的数据从数据模型中获取&#xff0c;从而实现…

固定资产管理措施怎么写

固定资产管理措施是指企业在进行固定资产管理时所采取的各种措施和方法。以下是一些常见的固定资产管理措施&#xff1a;  建立完善的固定资产管理制度。制定明确的资产采购、使用、维护、报废等流程和标准&#xff0c;确保资产管理的规范性和透明度。  采用先进的资产管理…

在 .NET 8 Preview 7 中推出 .NET MAUI:键盘加速键

作者&#xff1a;David Ortinau 排版&#xff1a;Alan Wang .NET MAUI 现已在 .NET 8 Preview 7 中推出&#xff0c;它引入了键盘加速键以及更多的修复和改进。这是我们发布 .NET 8 候选版本和正式发布&#xff08;GA&#xff09;版本之前的最后一个预览版本。随着发布日期的公…

六、DataGrip的基础使用

创建新数据库 1、点击MySQL图标&#xff0c;右键点击新建&#xff0c;然后选择框架(数据库) 2、输入数据库名称&#xff1a; 此处schema代表框架&#xff0c;和database(数据库)是同一性质的东西。 创建新的表 1、右键点击数据库&#xff0c;点击新建&#xff0c;再点击表 2…

设计模式-装饰模式

文章目录 一、简介二、基本概念三、装饰模式的结构和实现类图解析&#xff1a;装饰器的实现方式继承实现&#xff1a;组合实现&#xff1a;继承和组合对比 四、装饰模式的应用场景五、与其他模式的关系六、总结 一、简介 装饰模式是一种结构型设计模式&#xff0c;它允许动态地…

黑客常用的10大工具介绍

黑客技术一度被认为是一个神秘的特有领域&#xff0c;随着技术的进步和领域环境的进步&#xff0c;它已经成为一种非常普遍的现象。黑客技术可以用于有害目的&#xff0c;也可以用于发现系统中的漏洞&#xff0c;并通知系统属主&#xff0c;帮助他们更好地保护系统。 借助于一些…

【【萌新的STM32学习--24 USART的部分介绍】】

萌新的STM32学习–24 USART的部分介绍 STM32的USART的介绍 USART 英文解释是 通用同步异步收发器 UART 通用异步收发器 USART/UART 都可以与外部设备进行全双工异步通信 USART 我们常用的也是异步通信 USART 主要特征 1.全双工异步通信 2.单线半双工通信 3.单独的发送器和接…

股市里面怎么加杠杆?买股加杠杆如何应对市场波动与风险?

股市里面怎么加杠杆&#xff1f;买股加杠杆如何应对市场波动与风险&#xff1f;首先&#xff0c;让我们讨论如何在股市中加杠杆。主要有一下两种方式&#xff1a; 1. 通过杠杆交易平台&#xff1a;许多券商和金融机构提供杠杆交易平台。 2. 通过杠杆型交易基金&#xff1a;杠…

在QGIS中手动输入坐标文本添加点状矢量要素的一种方法

目录 一、前言 二、应用场景 三、实现思路 四、实验过程 1、创建一个临时矢量图层 2、给矢量图层新增要素 3、给新增要素的几何图形赋值 4、查看要素的几何图形 五、实验总结 一、前言 本文主要为QGIS点状矢量数据编辑方面的内容&#xff0c;不涉及编程方面。我们知道大…

一文了解性能测试常见的指标

一、什么是性能测试 性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。 我们可以认为性能测试是&#xff1a;通过在测试环境下对系统或构件的性能进行探测&#xff0c;用以验证在生产环境下系统性能是否达到预估的性能需求…

Vue3列表竖向滚动(包含使用swiper的翻页效果)

一、使用element-plus表格进行滚动&#xff1a; 可以满足的需求&#xff1a;表格一行一行竖向滚动&#xff0c;类似走马灯。 不能满足的需求&#xff1a;表格分页竖向滚动&#xff0c;有翻页的效果。 代码&#xff1a; <template><el-table:data"tableData"…

【LeetCode-中等题】236. 二叉树的最近公共祖先

文章目录 题目方法一&#xff1a;后序遍历 回溯 题目 方法一&#xff1a;后序遍历 回溯 解题的核心就是&#xff1a;采用后序遍历 讨论p&#xff0c;q是否在当前的root的两边&#xff0c;如在两边则返回当前节点root 如何不在两边&#xff0c;只要出现一个节点等于p或者q就…

怎么让模糊的图片变清晰?试试这几招吧

有时候我们自己拍摄的照片或者是从网上下载的壁纸、头像背景等&#xff0c;应用的时候觉得这个画质怎么这么模糊&#xff0c;这种图片模糊的情况应该怎么办呐&#xff1f;其实借助专业有效的修复工具&#xff0c;我们就可以快速将模糊的图片变清晰了&#xff0c;今天就给大家介…