使用SpringBoot + Vue + Redis实现验证码登录功能全过程

 更新时间:2025年10月21日 10:41:07   作者:乡下小哥编程  
在现代web应用中,用户验证是非常重要的一部分,这篇文章主要介绍了使用SpringBoot + Vue + Redis实现验证码登录功能的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

验证码在项目中使用到的较多,主要的目的是防止bl破解和自动化脚本攻击。验证码需要人工识别图片中的内容,可以组织批量的自动化攻击。同时可以减轻数据库的访问压力,验证码不通过的情况下,不去进行查表操作。这篇文章大致说明一下具体的实现过程~

实现效果演示

这里的图片二维码是后端接口返回的base64(图片转base64),然后渲染到页面部分。用户点击这个图片可以生成新的验证码。验证码的有效时长是1分钟、超过有效期 ,验证失效。(有效时长可以通过改变验证码存入Redis的时长来调整)。

实现过程大致说明

1、后端pom文件引入Redis依赖,redis 连接 等下相关配置;

2、生成验证码保存到Redis中(同时设置过期时间);

3、将生成的图片验证码以base64格式返回给前端,渲染出来;

4、用户输入的验证码和Redis的比对;

后端接口实现(核心部分)

验证码生成部分

    /**
     * 后台生成图形验证码 :有效
     * @param response
     * @param key
     */
    @GetMapping(value = "/randomImage/{key}")
    public Result randomImage(HttpServletResponse response, @PathVariable("key") String key){
        logger.info("进入后台生成图形验证码方法 ...");
        JSONObject jsonObject = new JSONObject();
        try {
            //生成验证码
            String code = RandomUtil.randomString(BASE_CHECK_CODES,4);
            //存到redis中
            String lowerCaseCode = code.toLowerCase();
            // 加入密钥作为混淆,避免简单的拼接,被外部利用,用户自定义该密钥即可
            logger.info("RedisKey: {}", key);
            String keyPrefix = Md5Util.md5Encode(key + SIGNATURE_SECRET, "utf-8");
            String realKey = keyPrefix + lowerCaseCode;
            redisUtil.removeAll(keyPrefix);
            redisUtil.set(realKey, lowerCaseCode, 60);
            logger.info("获取验证码,Redis key = {},checkCode = {}", realKey, code);
            
            //返回前端
            String base64 = RandImageUtil.generate(code);
            jsonObject.put("base64", base64);
            return Result.ok().data(jsonObject);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return Result.error().code(ResultCode.GET_VERIFY_CODE_ERROR.getCode())
                    .message(ResultCode.GET_VERIFY_CODE_ERROR.getMessage());
        }
    }

生成base64图片字符串

    /**
     * 生成base64字符串
     * @param resultCode
     * @return
     * @throws IOException
     */
    public static String generate(String resultCode) throws IOException {
        BufferedImage image = getImageBuffer(resultCode);
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        //写入流中
        ImageIO.write(image, IMG_FORMAT, byteStream);
        //转换成字节
        byte[] bytes = byteStream.toByteArray();
        //转换成base64串
        String base64 = Base64.getEncoder().encodeToString(bytes).trim();
        //删除 \r\n
        base64 = base64.replaceAll("\n", "").replaceAll("\r", "");
        //写到指定位置
        //ImageIO.write(bufferedImage, "png", new File(""));
        return BASE64_PRE+base64;
    }

验证部分,将用户输入的验证码和Redis存储的比对。

    @RequestMapping(value = "/Login/userLogin", method = RequestMethod.POST)
    public Result loginSystem(@RequestBody SysLoginModel sysLoginModel, HttpServletRequest request) {
        log.info("用户登录开始:{}", sysLoginModel);
        String captcha = sysLoginModel.getCaptcha();
        String checkKey = sysLoginModel.getCheckKey();
        if(captcha==null){
            return Result.error().code(ResultCode.VERIFY_CODE_ERROR.getCode())
                    .message(ResultCode.VERIFY_CODE_ERROR.getMessage());
        }
        String lowerCaseCaptcha = captcha.toLowerCase();
        String realKey = Md5Util.md5Encode(checkKey + SIGNATURE_SECRET, "utf-8") + lowerCaseCaptcha;
        Object checkCode = redisUtil.get(realKey);
        log.info("Redis存储验证码: {} , 用户输入验证码: {}", checkCode , lowerCaseCaptcha);
        if(checkCode == null || !checkCode.equals(lowerCaseCaptcha)) {
            return Result.error().code(ResultCode.VERIFY_CODE_NOT_EXIST.getCode()).message(ResultCode.VERIFY_CODE_NOT_EXIST.getMessage());
        }
       }

前端接口实现  (核心部分)

页面实现部分、用的vue2

<el-form-item prop="captcha">
<div class="captcha-box">
  <el-input
	v-model="form.captcha"
	placeholder="验证码"
	prefix-icon="el-icon-key"
  />
  <div class="captcha-img">
	<img
	  v-if="randCodeData.requestCodeSuccess"
	  style="margin-top: 2px; max-width: initial"
	  :src="randCodeData.randCodeImage"
	  @click="handleChangeCheckCode"
	/>
  </div>
</div>
</el-form-item>

js部分实现

    handleChangeCheckCode() {
      const _this = this;
      this.randCodeData.checkKey =
        new Date().getTime() + Math.random().toString(36).slice(-4); 
      this.$axios
        .getRandomImage(_this.randCodeData.checkKey)
        .then(function (resp) {
          if (resp.code == 200) {
            _this.randCodeData.randCodeImage = resp.data.base64;
            _this.randCodeData.requestCodeSuccess = true;
          } else {
            _this.$message.error(resp.message);
          }
        });
    },

总结 

到此这篇关于使用SpringBoot + Vue + Redis实现验证码登录功能的文章就介绍到这了,更多相关SpringBoot+Vue+Redis实现验证码登录内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java线程并发countdownlatch类使用示例

    java线程并发countdownlatch类使用示例

    javar的CountDownLatch是个计数器,它有一个初始数,等待这个计数器的线程必须等到计数器倒数到零时才可继续。
    2014-01-01
  • Java语言中的文件数据流示例详解

    Java语言中的文件数据流示例详解

    这篇文章主要为大家介绍了Java语言中的文件数据流示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • java实现马踏棋盘的算法

    java实现马踏棋盘的算法

    这篇文章主要为大家详细介绍了java实现马踏棋盘的算法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • java.math.BigDecimal的用法及加减乘除计算

    java.math.BigDecimal的用法及加减乘除计算

    这篇文章主要介绍了java.math.BigDecimal的用法及加减乘除计算,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • spring boot和spring cloud之间的版本关系

    spring boot和spring cloud之间的版本关系

    这篇文章主要介绍了spring boot和spring cloud之间的版本关系,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • Mybatis中的高级映射一对一、一对多、多对多

    Mybatis中的高级映射一对一、一对多、多对多

    这篇文章主要介绍了Mybatis中的高级映射一对一、一对多、多对多的相关资料,需要的朋友可以参考下
    2016-08-08
  • 如何解决IDEA没有新建servlet选项问题

    如何解决IDEA没有新建servlet选项问题

    这篇文章主要介绍了如何解决IDEA没有新建servlet选项问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • 解析spring boot与ireport 整合问题

    解析spring boot与ireport 整合问题

    本文通过实例代码给大家介绍了spring boot 与 ireport 整合问题,关于pom文件依赖的问题通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-10-10
  • Java创建树形结构算法实例代码

    Java创建树形结构算法实例代码

    本篇文章主要介绍了Java创建树形结构算法实例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-01-01
  • Spring MVC文件配置以及参数传递示例详解

    Spring MVC文件配置以及参数传递示例详解

    这篇文章主要给大家介绍了关于Spring MVC文件配置以及参数传递的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03

最新评论