首页 > 其他分享 >【shiro】13.验证码过滤器

【shiro】13.验证码过滤器

时间:2024-10-25 09:23:27浏览次数:6  
标签:13 code return String captchaEnabled 验证码 captchaType shiro

通过之前的学习,我们知道如果自定义过滤器的使用。接下来,查看ruoyi源码,我们需要在过滤器中实现验证码。

前提

思路

1. Shiro的配置页面,添加自定义过滤器。过滤器需要传递两个参数:  captchaEnabled (验证码开关)和  captchaType  (验证码类型)。

2. 新建自定义过滤器,继承抽象类 AccessControlFilter 。在这里实现方法 isAccessAllowed (过滤前操作)(重点)和 onAccessDenied 验证失败后处理方法。我们把页面获取到的验证码和Session中得到的验证码进行对比。每次对比成功后,都要清除Session。

3. 新建绘制验证码并保存Session的接口。

4. 前端页面,添加验证码提交和验证码图片,用于提交时对比和绘制验证码。

步骤

1. 添加自定义过滤器。在配置文件(application.yml)添加两个参数 captchaEnabled (验证码开关)和 captchaType (验证码类型)。

1 # shiro配置
2 shiro:
3   user:
4     loginUrl: /login
5     captchaEnabled : true
6     captchaType: math

 

ShiroConfiguration.java 添加配置器的引用。

 1 /**
 2  * 验证码开关
 3  */
 4 @Value("${shiro.user.captchaEnabled}")
 5 private boolean captchaEnabled;
 6 
 7 /**
 8  * 验证码类型
 9  */
10 @Value("${shiro.user.captchaType}")
11 private String captchaType;

 

在拦截器添加登录页面的验证码接口

 过滤器方法如下:

 1 /**
 2  * 自定义验证码
 3  * @return
 4  */
 5 private Filter myCaptcha() {
 6     MyCaptchaFilter myCaptchaFilter = new MyCaptchaFilter();
 7     myCaptchaFilter.setCaptchaEnabled(captchaEnabled);
 8     myCaptchaFilter.setCaptchaType(captchaType);
 9     return myCaptchaFilter;
10 }

2. 自定义验证码过滤器,继承抽象类 AccessControlFilter 。添加接收参数的方法。

 1 /**
 2  * 验证码开关
 3  */
 4 private boolean captchaEnabled = true;
 5 
 6 /**
 7  * 验证码类型
 8  */
 9 private String captchaType= "math";
10 
11 public void setCaptchaEnabled(boolean captchaEnabled) {
12     this.captchaEnabled = captchaEnabled;
13 }
14 
15 public void setCaptchaType(String captchaType) {
16     this.captchaType = captchaType;
17 }

继承过滤前验证方法。当获取到的接口类型为“post”时且开启验证码时,进行验证,否则不进行验证。(验证方法,对比post请求的code和Session是否一致),返回true则放行下一个拦截器,返回false则执行 onAccessDenied 代码。

 1  @Override
 2 protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
 3     HttpServletRequest httpServletRequest = (HttpServletRequest) request;
 4     if(!captchaEnabled || !"post".equals(httpServletRequest.getMethod().toLowerCase())){
 5         return true;
 6     }
 7     return validateResponse(httpServletRequest, httpServletRequest.getParameter(ShiroConstants.CURRENT_VALIDATECODE));  //  public static final String CURRENT_VALIDATECODE = "validateCode";
 8 }
 9 
10 private boolean validateResponse(HttpServletRequest request, String validateCode) {
11     Object obj = ShiroUtils.getSession().getAttribute("KAPTCHA_SESSION_KEY");
12     String code = String.valueOf(obj != null ? obj : "");
13     System.out.println("code:"+code);
14     System.out.println("validateCode:"+validateCode);
15     // 验证码清除,防止多次使用。
16     request.getSession().removeAttribute("KAPTCHA_SESSION_KEY");
17     if (StringUtils.isEmpty(validateCode) || !validateCode.equalsIgnoreCase(code))
18     {
19         return false;
20     }
21     return  true;
22 }

 验证后的处理方法。返回true则放行下一个拦截器,返回false,则不放行下一个拦截器。

1 @Override
2 protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
3     request.setAttribute(ShiroConstants.CURRENT_CAPTCHA, ShiroConstants.CAPTCHA_ERROR);//  request.setAttribute("captcha", "captchaError");
4     return false;
5 }

 3.新建绘制验证码并保存Session的接口。实际使用中,验证码的绘制可能更复杂,单独引用在其他地方。这里,简单引用随机生成N位数字的方式。使用BufferImage设置背景和每个字符。

 1 **
 2  * 图片验证码
 3  * 
 4  * @author ruoyi
 5  */
 6 @Controller
 7 @RequestMapping("/captcha")
 8 public class SysCaptchaController extends BaseController
 9 {
10     /**
11      * 页面验证码图片生成(并将图片存入session)
12      */
13     @GetMapping(value = "/captchaImage")
14     public ModelAndView getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
15         int width = 120;
16         int height = 40;
17         BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
18         // 生成验证码
19         String code = generateCode(4);
20         // 绘制验证码
21         drawCaptcha(bufferedImage, code);
22         // 将验证码存入session
23         request.getSession().setAttribute("KAPTCHA_SESSION_KEY", code);
24         // 设置响应头
25         response.setContentType("image/jpeg");
26         response.setHeader("Pragma", "No-cache");
27         response.setHeader("Cache-Control", "no-cache");
28         response.setDateHeader("Expires", 0);
29         // 输出图片
30         ImageIO.write(bufferedImage,"jpg",response.getOutputStream());
31 
32         return  null;
33     }
34 
35     /**
36      * 生成验证码
37      * @param length
38      * @return
39      */
40     private String generateCode(int length){
41         Random random = new Random();
42         StringBuffer sb = new StringBuffer();
43         for (int i = 0; i < length; i++) {
44             sb.append(random.nextInt(10));
45         }
46         return sb.toString();
47     }
48 
49     /**
50      * 绘制验证码(可以自定义验证码的样式和细节)
51      * @param bufferedImage
52      * @param code
53      */
54     private void drawCaptcha(BufferedImage bufferedImage, String code) {
55         Graphics graphics = bufferedImage.getGraphics();
56         Random random = new Random();
57         // 设置背景
58         graphics.setColor(Color.WHITE);
59         graphics.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());
60         // 随机设置每个字符的颜色
61         for (int i = 0; i < code.length(); i++) {
62             Font font = new Font("Times New Roman", Font.BOLD, 30);
63             graphics.setColor(getColor(random));
64             graphics.setFont(font);
65             graphics.drawString(String.valueOf(code.charAt(i)), 30*i + 10, 30);
66         }
67 
68         graphics.dispose();
69     }
70 
71     // 字符随机颜色
72     private static Color getColor(Random random) {
73         return new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
74     }
75 
76 }

4. 前端页面,添加验证码提交和验证码图片,用于提交时对比和绘制验证码。 Math.random() 用于生成随机数。src路径变化,则会调用后台接口,改变验证码。

1 <div  th:if="${captchaEnabled==true}">
2     <div >
3         验证码:<input type="text" name="validateCode" placeholder="验证码" maxlength="5" />
4     </div>
5     <div >
6         <img th:src="/captcha/captchaImage"  title="点击刷新验证码" width="120" height="40" onclick="this.src='/captcha/captchaImage?'+Math.random()" />
7     </div>
8 </div>

 

标签:13,code,return,String,captchaEnabled,验证码,captchaType,shiro
From: https://www.cnblogs.com/luyj00436/p/18474582

相关文章

  • macOS 13 Ventura (苹果最新系统)v13.7正式版
    Apple今日发布了macOS的下一个版本,称为macOSVentura,它具有多项新功能,包括StageManager、ContinuityCamera、新的安全更新等。完整的兼容性列表如下:iMac(2017年及更高版本)iMacProMacBookair(2018年及更新机型)MacBookPro(2017年及更新机型)MacPro(2019年及更新机......
  • 适用于 Windows 11/10 电脑 的 13 个最佳文件恢复软件
    如果您由于系统故障、硬件损坏、人为错误或病毒攻击而丢失了重要文件或文件夹。不用担心,因为我们随时为您提供帮助!借助正确的文件恢复工具,您可以立即检索计算机上不同类型的文件。如果你有为您的文件创建备份,你不用担心,但是如果你没有备份怎么办?然后,您需要获得适用于Windows1......
  • 13.4K+ Star!DeepFace:一个轻量级人脸识别和面部属性分析库
    DeepFace简介DeepFace[1]是一个用于Python的轻量级人脸识别和面部属性分析(年龄、性别、情绪和种族)库。DeepFace利用深度学习进行人脸识别和分析,它通过封装多种先进的人脸识别模型,提供了一个简单易用的接口。用户无需深入了解背后的复杂过程,只需通过简单的函数调用来实现......
  • 梦熊 NOIP 13连测 #13
    赛时100+75+30+0A.求对于区间\([l,r]\)的答案,转换成$ans(R)-ans(L-1)\(,\)ans(i)$表示小于等于\(i\)的元素个数。对于\(x\),二分小于等于\(x\)的个数,可以直接对于二分的这个数q次操作判断,因为如果它可以小于它的一定也可以。时间复杂度\(O(Q\logn)\)B.75pt......
  • Android 13.0 系统framework修改低电量关机值为2%
    1.前言在13.0的系统rom产品定制化开发中,在系统关于低电量关机的值,每个平台都不同,根据实际开发底层硬件的要求看实际情况来调整这个值,所以需要分析相关的电量变化执行的代码流程,来实现这个功能,接下来看具体怎么实现2.系统framework修改低电量关机值为2%的核心类frameworks\b......
  • 处理异常的13条军规
    前言在我们日常工作中,经常会遇到一些异常,比如:NullPointerException、NumberFormatException、ClassCastException等等。那么问题来了,我们该如何处理异常,让代码变得更优雅呢?1不要忽略异常不知道你有没有遇到过下面这段代码:反例:Longid=null;try{id=Long.parseLon......
  • CF1139C. Edgy Trees 题解 并查集
    题目链接:https://codeforces.com/problemset/problem/1139/C视频讲解:https://www.bilibili.com/video/BV1tZ1FYPELp?p=3我们可以求总方案数-不满足条件的方案数。设一个不包含黑色边的极大连通块的大小为\(sz_i\)。则答案为\[n^k-\sum\{sz_i^k\}\]示例程序:#include......
  • MT1371-MT1380 码题集 (c 语言详解)
    目录        MT1371·所有路径        MT1372·矩阵清零        MT1373·亲和数         MT1374·Pronic数         MT1375·4和7的序列        MT1376·小码哥的数学        MT1377·模乘逆元      ......
  • 【Shiro】12.自定义过滤器
    通过查看若依源码(ruoyi-framework)下的过滤器文件(src.main.java.com.ruoyi.framework.config.ShiroConfig)可以发现设置了过滤器。过滤器(Filter)是JavaServlet技术中的一个重要部分,主要用于在Servlet处理请求之前或响应之后对数据进行某些处理。可以这么理解。如果类比到......
  • 蓝桥杯EDA赛道经验分享(一)&12、13、14届省赛客观题知识点
    一、经验分享1.文件提取离线模式——>文件——>(大压缩包)导入专业版——>导入文件;(小压缩包)提取库文件。2.布线规则先根据参赛文件改布线规则(间距,线宽)。3.PCBlayout注意事项(1)避免重叠:确保元件间无物理重叠,为布线留出足够空间。(2)元件放置:大功率元件及发热元件应分散布局......