亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

使用SpringBoot?+?Vue?+?Redis實(shí)現(xiàn)驗(yàn)證碼登錄功能全過程

 更新時(shí)間:2025年10月21日 10:41:07   作者:鄉(xiāng)下小哥編程  
在現(xiàn)代web應(yīng)用中,用戶驗(yàn)證是非常重要的一部分,這篇文章主要介紹了使用SpringBoot?+?Vue?+?Redis實(shí)現(xiàn)驗(yàn)證碼登錄功能的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

驗(yàn)證碼在項(xiàng)目中使用到的較多,主要的目的是防止bl破解和自動(dòng)化腳本攻擊。驗(yàn)證碼需要人工識(shí)別圖片中的內(nèi)容,可以組織批量的自動(dòng)化攻擊。同時(shí)可以減輕數(shù)據(jù)庫的訪問壓力,驗(yàn)證碼不通過的情況下,不去進(jìn)行查表操作。這篇文章大致說明一下具體的實(shí)現(xiàn)過程~

實(shí)現(xiàn)效果演示

這里的圖片二維碼是后端接口返回的base64(圖片轉(zhuǎn)base64),然后渲染到頁面部分。用戶點(diǎn)擊這個(gè)圖片可以生成新的驗(yàn)證碼。驗(yàn)證碼的有效時(shí)長是1分鐘、超過有效期 ,驗(yàn)證失效。(有效時(shí)長可以通過改變驗(yàn)證碼存入Redis的時(shí)長來調(diào)整)。

實(shí)現(xiàn)過程大致說明

1、后端pom文件引入Redis依賴,redis 連接 等下相關(guān)配置;

2、生成驗(yàn)證碼保存到Redis中(同時(shí)設(shè)置過期時(shí)間);

3、將生成的圖片驗(yàn)證碼以base64格式返回給前端,渲染出來;

4、用戶輸入的驗(yàn)證碼和Redis的比對(duì);

后端接口實(shí)現(xiàn)(核心部分)

驗(yàn)證碼生成部分

    /**
     * 后臺(tái)生成圖形驗(yàn)證碼 :有效
     * @param response
     * @param key
     */
    @GetMapping(value = "/randomImage/{key}")
    public Result randomImage(HttpServletResponse response, @PathVariable("key") String key){
        logger.info("進(jìn)入后臺(tái)生成圖形驗(yàn)證碼方法 ...");
        JSONObject jsonObject = new JSONObject();
        try {
            //生成驗(yàn)證碼
            String code = RandomUtil.randomString(BASE_CHECK_CODES,4);
            //存到redis中
            String lowerCaseCode = code.toLowerCase();
            // 加入密鑰作為混淆,避免簡(jiǎn)單的拼接,被外部利用,用戶自定義該密鑰即可
            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("獲取驗(yàn)證碼,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);
        //轉(zhuǎn)換成字節(jié)
        byte[] bytes = byteStream.toByteArray();
        //轉(zhuǎn)換成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;
    }

驗(yàn)證部分,將用戶輸入的驗(yàn)證碼和Redis存儲(chǔ)的比對(duì)。

    @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存儲(chǔ)驗(yàn)證碼: {} , 用戶輸入驗(yàn)證碼: {}", 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());
        }
       }

前端接口實(shí)現(xiàn)  (核心部分)

頁面實(shí)現(xiàn)部分、用的vue2

<el-form-item prop="captcha">
<div class="captcha-box">
  <el-input
	v-model="form.captcha"
	placeholder="驗(yàn)證碼"
	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部分實(shí)現(xiàn)

    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);
          }
        });
    },

總結(jié) 

到此這篇關(guān)于使用SpringBoot + Vue + Redis實(shí)現(xiàn)驗(yàn)證碼登錄功能的文章就介紹到這了,更多相關(guān)SpringBoot+Vue+Redis實(shí)現(xiàn)驗(yàn)證碼登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java線程并發(fā)countdownlatch類使用示例

    java線程并發(fā)countdownlatch類使用示例

    javar的CountDownLatch是個(gè)計(jì)數(shù)器,它有一個(gè)初始數(shù),等待這個(gè)計(jì)數(shù)器的線程必須等到計(jì)數(shù)器倒數(shù)到零時(shí)才可繼續(xù)。
    2014-01-01
  • Java語言中的文件數(shù)據(jù)流示例詳解

    Java語言中的文件數(shù)據(jù)流示例詳解

    這篇文章主要為大家介紹了Java語言中的文件數(shù)據(jù)流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • java實(shí)現(xiàn)馬踏棋盤的算法

    java實(shí)現(xiàn)馬踏棋盤的算法

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)馬踏棋盤的算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • java.math.BigDecimal的用法及加減乘除計(jì)算

    java.math.BigDecimal的用法及加減乘除計(jì)算

    這篇文章主要介紹了java.math.BigDecimal的用法及加減乘除計(jì)算,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • spring boot和spring cloud之間的版本關(guān)系

    spring boot和spring cloud之間的版本關(guān)系

    這篇文章主要介紹了spring boot和spring cloud之間的版本關(guān)系,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-08-08
  • Mybatis中的高級(jí)映射一對(duì)一、一對(duì)多、多對(duì)多

    Mybatis中的高級(jí)映射一對(duì)一、一對(duì)多、多對(duì)多

    這篇文章主要介紹了Mybatis中的高級(jí)映射一對(duì)一、一對(duì)多、多對(duì)多的相關(guān)資料,需要的朋友可以參考下
    2016-08-08
  • 如何解決IDEA沒有新建servlet選項(xiàng)問題

    如何解決IDEA沒有新建servlet選項(xiàng)問題

    這篇文章主要介紹了如何解決IDEA沒有新建servlet選項(xiàng)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 解析spring boot與ireport 整合問題

    解析spring boot與ireport 整合問題

    本文通過實(shí)例代碼給大家介紹了spring boot 與 ireport 整合問題,關(guān)于pom文件依賴的問題通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-10-10
  • Java創(chuàng)建樹形結(jié)構(gòu)算法實(shí)例代碼

    Java創(chuàng)建樹形結(jié)構(gòu)算法實(shí)例代碼

    本篇文章主要介紹了Java創(chuàng)建樹形結(jié)構(gòu)算法實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-01-01
  • Spring MVC文件配置以及參數(shù)傳遞示例詳解

    Spring MVC文件配置以及參數(shù)傳遞示例詳解

    這篇文章主要給大家介紹了關(guān)于Spring MVC文件配置以及參數(shù)傳遞的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評(píng)論