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

一、登录流程

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.mfbz.cn/a/486457.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一个优秀的开源ChatGpt外壳项目(lobe-chat)

lobe-chat 简介&#xff1a; 开源、现代化设计的 ChatGPT/LLMs 聊天应用与开发框架支持语音合成、多模态、可扩展的插件系统&#xff0c;一键免费拥有你自己的 ChatGPT/Gemini/Ollama 应用。 下载lobe-chat lobe-chat项目开源地址&#xff1a;GitHub - lobehub/lobe-chat: &am…

MySQL高可用解决方案――从主从复制到InnoDB Cluster架构

2024送书福利正式起航 关注「哪吒编程」&#xff0c;提升Java技能 文末送5本《MySQL高可用解决方案――从主从复制到InnoDB Cluster架构》 大家好&#xff0c;我是哪吒。 爱奇艺每天都为数以亿计的用户提供7x24小时不间断的视频服务。通过爱奇艺的平台&#xff0c;用户可以…

查看Linux系统重启的四种基本命令

目录 前言1. last2. uptime3. journalctl4. dmesg 前言 对于排查其原因推荐阅读&#xff1a;详细分析服务器自动重启原因&#xff08;涉及Linux、Window&#xff09; 在Linux中&#xff0c;有多种命令可以查看系统重启的信息 以下是其中一些常用的命令及其解释&#xff1a; …

跨时钟域学习记录(一)

亚稳态 亚稳态是电平介于高低电平之间的一种暂时状态。在同步系统中&#xff0c;当寄存器的信号无法满足建立时间和保持时间时&#xff0c;输出端的信号就可能出现亚稳态。在异步系统中&#xff0c;亚稳态并非一定在建立时间和保持时间无法满足时出现。   受噪声、温度、电压…

ZYNQ学习之PetaLinux开发环境搭建

基本都是摘抄正点原子的文章&#xff1a;<领航者 ZYNQ 之嵌入式Linux 开发指南 V3.2.pdf&#xff0c;因初次学习&#xff0c;仅作学习摘录之用&#xff0c;有不懂之处后续会继续更新~ FTP&#xff1a;File Transfer Protocol 一、Ubuntu 和 Windows 文件互传 1.1、开启 Ubu…

HarmonyOS系统开发ArkTS常用组件文本及参数(五)

目录 一、Text组件 1、Text组件案例 二、Text组件参数 1、string字符串类型 2、Resources类型 2.1、resources中内容配置 base/element/string.json 中的内容 zh_US/element/string.json 中的内容 es_US/element/string.json 中的内容 2.2、环境适配 适配英文 适配中文…

初探Ruby编程语言

文章目录 引言一、Ruby简史二、Ruby特性三、安装Ruby四、命令行执行Ruby五、Ruby的编程模型六、案例演示结语 引言 大家好&#xff0c;今天我们将一起探索一门历史悠久、充满魅力的编程语言——Ruby。Ruby是由松本行弘&#xff08;Yukihiro Matsumoto&#xff09;于1993年发明…

计算机网络实验——学习记录二(HTTP协议)

1. Linux主机上连接互联网的网络接口是&#xff1a;ens33。 2. 在显示过滤器&#xff08;Filter&#xff09;中输入“ http.host www.zzu.edu.cn”&#xff0c;筛选出HTTP协议报文首部行中包含“ Host&#xff1a;www.zzu.edu.cn”的报文&#xff08;目的地址是Web服务器的报…

微前端——qiankun

一、微前端 微前端是指存在于浏览器中的微服务&#xff0c;其借鉴了后端微服务的架构理念&#xff0c;将微服务的概念扩展到前端。即将一个大型的前端应用拆分为成多个模块&#xff0c;每个微前端模块可以有不同的团队开发并进行管理&#xff0c;且可以自主选择框架&#xff0…

RSTP、MSTP、VRRP

RSTP协议原理与配置 问题一、STP的收敛延时&#xff08;30秒&#xff08;有BP端口情况下RP端口down&#xff09;或者50秒&#xff08;没有BP端口情况下RP端口down&#xff09;&#xff09; RSTP&#xff1a;Rapid Spanning Tree Protocol RSTP和STP从原理流程上一样&#xf…

Vivado的SIMULATION的Scope和source的层级怎么看

一、查看source source的层级可以很容易看出来&#xff0c;上面是tb文件的名称&#xff0c;下面的 axi_full_wrapper : axi_full_wrapper (axi full wrapper.v) (1)中&#xff0c;右边的那个axi_full_wrapper是模块名称&#xff0c;也是源文件名称&#xff08;因为module之后接…

天正T20V10 下载地址及安装教程

天正软件是一家专业的工程设计软件和解决方案提供商&#xff0c;主要致力于建筑、结构、暖通、给排水、电气等领域的设计和施工工程。他们开发和提供多种软件产品&#xff0c;涵盖了建筑设计、结构设计、暖通空调设计、给排水设计、电气设计等方面。 天正软件的产品具有丰富的…

Python的7大就业方向!小白适合哪个方向?学了Python能干什么?

每个程序员都有自己主要的开发语言&#xff0c;并且都认为自己的语言是最好的&#xff0c;懂的朋友在评论区里打个666~ 我的主要开发语言是Python&#xff0c;Python在我们编程圈里呢&#xff0c;是非常流行。 最近两年甚至火出了编程圈&#xff0c;越来越多不是程序员的朋友也…

Vulnhub:DR4G0N B4LL: 1

目录 信息收集 1、arp 2、nmap WEB web信息收集 gobuster 隐藏目录发现 图片隐写 ssh登录 提权 get user 系统信息收集 get root 信息收集 1、arp ┌──(root㉿ru)-[~/kali/vulnhub] └─# arp-scan -l …

谷歌seo怎么优化产品推广?

想要在谷歌SEO上优化产品推广&#xff0c;关键在于理解和利用搜索引擎的工作原理来提升你的产品在搜索结果中的可见性&#xff0c;结构化数据就很重要了&#xff0c;它能让谷歌更容易理解你的页面内容&#xff0c;让他知道你这个页面不是文章页&#xff0c;主页&#xff0c;而是…

【AI】大模型API调研及推荐

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 【AI】大模型API调研及推荐引入调研KimiAPI对接 国内GPT4的转发API对接 总结 【AI…

生态系统碳循环模型CENTURY 建模方法

原文链接&#xff1a;生态系统碳循环模型CENTURY 建模方法https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247598976&idx6&snb684175e24c5600a69033a838535078d&chksmfa820267cdf58b71cb1d119dfe101f7b3a312e8c0b1b8ef4adbef2894aa902b290ef7e091de2&am…

Lightroom Classic 2024,成就专业摄影梦想mac/win版

Lightroom Classic 2024是一款功能强大的数字图像处理和管理工具&#xff0c;专为摄影师和摄影爱好者设计。它提供了丰富的照片调整、处理、管理和分享功能&#xff0c;帮助用户轻松管理、编辑和展示他们的照片。 Lightroom Classic 2024软件获取 首先&#xff0c;Lightroom C…

MixKG: Mixing for harder negative samples in knowledge graph---没代码

摘要 知识图嵌入(KGE)旨在将实体和关系表示为低维向量&#xff0c;用于许多现实世界的应用。实体和关系的表征是通过对比正负三联体来学习的。因此&#xff0c;高质量的阴性样品在KGE中是非常重要的。然而&#xff0c;目前的KGE模型要么依赖于简单的负抽样方法&#xff0c;这使…

为什么有的测径仪断电重启后自动恢复,有的手动恢复

关键字&#xff1a;测径仪断电重启&#xff0c;测径仪自动恢复&#xff0c;测径仪严重故障&#xff0c;测径仪手动恢复&#xff0c;蓝鹏测控 测径仪断电重启后能否自动恢复&#xff0c;主要取决于其内部的设计、配置以及所面对的具体问题。 对于大多数智能测径仪来说&#xf…
最新文章