RuoYi-Vue-Plus(登录流程-验证码生成)

news2024/12/23 14:02:24

一、登录流程

1- 进入登录页面,调用 com.ruoyi.web.controller.common.CaptchaController 类中的

captchaImage 方法,生成base64的图片 以及 UUID

2-  提交 登录信息 + 验证码 + uuid 比对

错误:返回错误信息,删除缓存的验证码

成功: 拿到token,加入缓存        

二、验证码生成 

1-前台代码配置

前端login 页面中,图片如下:

 <div class="login-code">
          <img :src="codeUrl" @click="getCode" class="login-code-img"/>
        </div>

methods 函数中,captchaEnabled  是验证码是否开启的属性,以及注册功能开关,定义在data中如下:

  data() {
      // 验证码开关
      captchaEnabled: true,
      // 注册开关
      register: false,
      redirect: undefined
    };

  },

在页面 created 时候 ,调用getCode 生成验证码,返回页面

  created() {
    this.getCode();
    this.getCookie();
}

  methods: {
    getCode() {
      getCodeImg().then(res => {
        this.captchaEnabled = res.data.captchaEnabled === undefined ? true : res.data.captchaEnabled;
        if (this.captchaEnabled) {
          this.codeUrl = "data:image/gif;base64," + res.data.img;
          this.loginForm.uuid = res.data.uuid;
        }
      });
    },

....................

 

src\api\login.js 中,请求后台

// 获取验证码
export function getCodeImg() {
  return request({
    url: '/captchaImage',
    headers: {
      isToken: false
    },
    method: 'get',
    timeout: 20000
  })
}

返回如下:

{
    "code": 200,
    "msg": "操作成功",
    "data": {
        "img": "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",
        "captchaEnabled": true,
        "uuid": "2f329cd71b96426cac682791a058a3a6"
    }
}
2-后台代码配置

系参数配置 菜单中,sys.account.captchaEnabled  设置了关于验证码是否开启的配置

 后台接口:  com.ruoyi.web.controller.common.CaptchaController 类中,逻辑如下:

1- 判断验证码功能是否启用

        redis缓存中获取 sys.account.captchaEnabled  判断是否开启验证码 ,配置如上截图

2-  生成uuid

        这样根据uuid 就能在缓存中找到验证码

        String uuid = IdUtil.simpleUUID();
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;

3- 生成验证码

        CaptchaType captchaType = captchaProperties.getType();   

   CaptchaType :ruoyi-admin中yml配置 (验证码类型、干扰线等等配置)
captcha:
  # 页面 <参数设置> 可开启关闭 验证码校验
  # 验证码类型 math 数组计算 char 字符验证
  type: MATH
  # line 线段干扰 circle 圆圈干扰 shear 扭曲干扰
  category: CIRCLE
  # 数字验证码位数
  numberLength: 1
  # 字符验证码长度
  charLength: 4

4- spel表达式 (spel 很强大 可以自己看看)

如果是数字,计算结果

if (isMath) {
    ExpressionParser parser = new SpelExpressionParser();
    Expression exp = parser.parseExpression(StringUtils.remove(code, "="));
    code = exp.getValue(String.class);
}
5- 保存到缓存中,设置过期时间
RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
        

详细代码如下:

 

 /**
     * 生成验证码
     */
    @GetMapping("/captchaImage")
    public R<Map<String, Object>> getCode() {
        Map<String, Object> ajax = new HashMap<>();
        //redis缓存中获取 sys.account.captchaEnabled
        boolean captchaEnabled = configService.selectCaptchaEnabled();
        ajax.put("captchaEnabled", captchaEnabled);
        //是否需要验证码
        if (!captchaEnabled) {
            return R.ok(ajax);
        }
        // 保存验证码信息
        String uuid = IdUtil.simpleUUID();
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
        
        // 生成验证码
        CaptchaType captchaType = captchaProperties.getType();
        boolean isMath = CaptchaType.MATH == captchaType;
        Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength();
        CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length);
        AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
        captcha.setGenerator(codeGenerator);
        captcha.createCode();
        String code = captcha.getCode();
        if (isMath) {
            ExpressionParser parser = new SpelExpressionParser();
            Expression exp = parser.parseExpression(StringUtils.remove(code, "="));
            code = exp.getValue(String.class);
        }
        RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
        ajax.put("uuid", uuid);
        ajax.put("img", captcha.getImageBase64());
        return R.ok(ajax);
    }

 三、手机验证、短信验证

com.ruoyi.web.controller.common.CaptchaController  类中还有其他验证方法:

smsCaptcha 短信验证码
captchaEmail 邮箱验证码

都是保存到redis中,然后通过uuid拿出来校验,和上门逻辑一样

/**
     * 短信验证码
     *
     * @param phonenumber 用户手机号
     */
    @GetMapping("/captchaSms")
    public R<Void> smsCaptcha(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) {
        String key = CacheConstants.CAPTCHA_CODE_KEY + phonenumber;
        String code = RandomUtil.randomNumbers(4);
        RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
        // 验证码模板id 自行处理 (查数据库或写死均可)
        String templateId = "";
        LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
        map.put("code", code);
        SmsBlend smsBlend = SmsFactory.createSmsBlend(SupplierType.ALIBABA);
        SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map);
        if (!"OK".equals(smsResponse.getCode())) {
            log.error("验证码短信发送异常 => {}", smsResponse);
            return R.fail(smsResponse.getMessage());
        }
        return R.ok();
    }

    /**
     * 邮箱验证码
     *
     * @param email 邮箱
     */
    @GetMapping("/captchaEmail")
    public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") String email) {
        if (!mailProperties.getEnabled()) {
            return R.fail("当前系统没有开启邮箱功能!");
        }
        String key = CacheConstants.CAPTCHA_CODE_KEY + email;
        String code = RandomUtil.randomNumbers(4);
        RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
        try {
            MailUtils.sendText(email, "登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。");
        } catch (Exception e) {
            log.error("验证码短信发送异常 => {}", e.getMessage());
            return R.fail(e.getMessage());
        }
        return R.ok();
    }

 

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

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

相关文章

vivado Modifying Logic

修改逻辑 在中实现后&#xff0c;可以修改非只读逻辑对象的属性Vivado IDE以及Tcl。 注意&#xff1a;有关Tcl命令的更多信息&#xff0c;请参阅Vivado Design Suite Tcl命令参考指南&#xff08;UG835&#xff09;&#xff0c;或键入&#xff1c;command&#xff1e;-help。…

SEO 谷歌浏览器模拟baodu蜘蛛 模拟UA 设置UA

目录 前言baidu UA操作设置百度UA 前言 要在谷歌浏览器中设置用户代理&#xff08;User Agent&#xff09;来模拟百度蜘蛛&#xff0c;您可以按照以下步骤进行操作 baidu UA Mozilla/5.0 (compatible; Baiduspider-render/2.0; http://www.baidu.com/search/spider.html)操作…

Linux(1)常用指令总结大全

1、firewall-cmd 1.1 打开443/TCP端口 firewall-cmd --add-port443/tcp 1.2 永久打开3690/TCP端口 firewall-cmd --permanent --add-port3690/tcp ​ # 永久打开端口好像需要reload一下&#xff0c;临时打开好像不用&#xff0c;如果用了reload临时打开的端口就失效了 # …

【无标题】C高级325

练习1&#xff1a;输入一个数&#xff0c;实现倒叙123-》321 练习2&#xff1a;输入一个&#xff0c;判断是否是素数 练习3&#xff1a;输入一个文件名&#xff0c; 判断是否在家目录下存在, 如果是一个目录&#xff0c;则直接输出是目录下的sh文件的个数 如果存在则判断是否是…

java常用应用程序编程接口(API)——IO流概述及字节流的使用

前言&#xff1a; IO流和File是用于把数据存放在硬盘里的工具。File可以把文件存至硬盘&#xff0c;但不能更改里面的数据。通过IO流可以改写硬盘里的数据。整理下学习笔记&#xff0c;打好基础&#xff0c;daydayup!!! IO流 I指Input&#xff0c;称为输入流&#xff1a;负责把…

【好书推荐2】AI提示工程实战:从零开始利用提示工程学习应用大语言模型

【好书推荐2】AI提示工程实战&#xff1a;从零开始利用提示工程学习应用大语言模型 写在最前面AI辅助研发方向一&#xff1a;AI辅助研发的技术进展方向二&#xff1a;行业应用案例方向三&#xff1a;面临的挑战与机遇方向四&#xff1a;未来趋势预测方向五&#xff1a;与法规的…

扬州大数据局领导一行参访百望云 探索新质生产力在百态千业的落地场景

​ 在当前全球经济一体化的大背景下&#xff0c;新质生产力的发展代表着科技进步、产业升级和商业模式创新的方向。特别两会期间&#xff0c;新质生产力概念爆火&#xff0c;也体现出我国政府高度重视新质生产力&#xff0c;将其作为实现高质量发展的重要支柱。 在此背景下&…

Day20 代码随想录(1刷) 二叉树

目录 654. 最大二叉树 617. 合并二叉树 700. 二叉搜索树中的搜索 98. 验证二叉搜索树 654. 最大二叉树 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。递归地在最大值 左边 的 子数…

今日arXiv最热NLP大模型论文:微软重磅:AgentAI,下一代人工智能的关键

人工智能的发展已从简单算法进化到复杂的大型基础模型&#xff0c;尤其在理解开放世界环境中的感官信息方面取得显著进步。然而&#xff0c;关键转折点在于从过度简化方法转向强调整体运作的系统&#xff0c;催生了Agent AI的兴起。Agent AI将大型基础模型整合到代理行动中的具…

如何实现无公网IP及服务器实现公网环境企业微信网页应用开发调试

文章目录 1. Windows安装Cpolar2. 创建Cpolar域名3. 创建企业微信应用4. 定义回调本地接口5. 回调和可信域名接口校验6. 设置固定Cpolar域名7. 使用固定域名校验 企业微信开发者在应用的开发测试阶段&#xff0c;应用服务通常是部署在开发环境&#xff0c;在有数据回调的开发场…

❤ leetCode简易题1-两数之和、简易2--回文数判断、简易14-最长公共前缀

❤ leetCode简易题1-两数之和、简易题14- 最长公共前缀 1、简易1-两数之和 ① 题目要求 数字A B target&#xff0c;以target为求和结果&#xff0c;找出数组中符合的A、B数字下标。 第一次做的时候完全脑子一片蒙&#xff0c;随后认真看了看题目发现是发现找符合target和…

rust中字符串String常用方法和注意事项

Rust 中通常说的字符串指的是&#xff1a;String 和 &str(字符串字面值、或者叫字符串切片)这两种类型。str是rust中基础字符串类型&#xff0c;String是标准库里面的类型。Rust 中的字符串本质上是&#xff1a;Byte的集合&#xff08;Vec<u8>&#xff09; 基础类型…

职场口才提升之道

职场口才提升之道 在职场中&#xff0c;口才的重要性不言而喻。无论是与同事沟通协作&#xff0c;还是向上级汇报工作&#xff0c;亦或是与客户洽谈业务&#xff0c;都需要具备良好的口才能力。一个出色的职场人&#xff0c;除了拥有扎实的专业技能外&#xff0c;还应具备出色…

gsxt cookie:__jsl_clearance_s 参数研究获取

gsxt cookie&#xff1a;__jsl_clearance_s 参数研究获取 今天尝试了一下 gsxt 网站中 cookie __jsl_clearance_s 参数解密 抓包 打开 fiddler 抓包工具&#xff0c;新建无痕浏览器页面刷新后得到抓包数据 发现后续的所有的请求都会携带这两个加密参数 __jsl_clearance_s17…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之六 简单图像倾斜校正处理效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之六 简单图像倾斜校正处理效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之六 简单图像倾斜校正处理效果 一、简单介绍 二、简单图像倾斜校正处理效果实现原理 三、简单图像倾斜校正…

2024年升级_python风控建模实战lendingClub_新增2020年数据(14万条)

作者Toby&#xff0c;来源公众号&#xff1a;python风控模型《python风控建模实战lendingClub_新增2020年数据&#xff08;14万条&#xff09;》 公告通知&#xff0c;我方重庆未来之智信息技术咨询服务有限公司自研课程《python风控建模实战lendingClub》2024年升级&#xff…

20240325数据驱动的机器学习预测单层二维材料力学性能

本论文使用模型主要有Mo,W,S,Se原子组成的单层二维材料。大小为30nmx30nm&#xff0c;中间有切口&#xff0c;切口大小从无切口以1nm增长到5nm&#xff0c;加载方向垂直于切口方向&#xff0c;并且分锯齿型和扶手椅型方向。 使用MD对模型进行拉伸&#xff0c;一共288个模型。 …

题目42—接雨水

题目来源于LeetCode 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 方法&#xff1a;使用单调栈。找到中间凹槽位置&#xff0c;并利用单调栈找出其左边的第一个最高柱子&#xff0c;右边的第一个最高柱…

NKCTF 2024(三月周报比赛一)

web My first cms 扫目录找到管理员界面登陆&#xff0c;账号Admin&#xff0c;密码Admin123,账号可以根据forget来进行查询是否存在&#xff0c;然后进行弱密码攻击&#xff0c;这里网上有两种rce&#xff0c;一种sstl一种代码执行 我用的是第二种 EXtension>use defined…

上班几周了,

过年回来后&#xff0c;时间变得飞快&#xff0c;很多事情都是马上要去干&#xff0c;而且又是很着急的事&#xff0c;呵呵&#xff0c;真的要干趴了 然后——经历了第一次年后的周末连续加班出版本保量产&#xff0c;经历了加班到凌晨3点调试问题&#xff0c;经历我们在疯狂的…