最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

前言

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

實現(xiàn)效果演示

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

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

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

2、生成驗證碼保存到Redis中(同時設置過期時間);

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

4、用戶輸入的驗證碼和Redis的比對;

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

驗證碼生成部分

    /**
     * 后臺生成圖形驗證碼 :有效
     * @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);
        //轉換成字節(jié)
        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());
        }
       }

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

頁面實現(xiàn)部分、用的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部分實現(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);
          }
        });
    },

總結 

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

相關文章

  • Java關鍵字之native詳解

    Java關鍵字之native詳解

    這篇文章主要為大家介紹了Java關鍵字之native,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • Springboot+mybatis-plus+注解實現(xiàn)數(shù)據(jù)權限隔離

    Springboot+mybatis-plus+注解實現(xiàn)數(shù)據(jù)權限隔離

    本文將結合實例代碼,介紹Springboot+mybatis-plus+注解實現(xiàn)數(shù)據(jù)權限隔離,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2021-07-07
  • Spring創(chuàng)建Bean的八種主要方式詳解

    Spring創(chuàng)建Bean的八種主要方式詳解

    Spring(尤其是 Spring Boot)提供了多種方式來讓容器創(chuàng)建和管理 Bean,@Component、@Configuration + @Bean、@EnableConfigurationProperties 都是常見方式,下面我為你系統(tǒng)地梳理 Spring 創(chuàng)建 Bean 的所有主要方式,并說明它們的使用場景和區(qū)別,需要的朋友可以參考下
    2025-08-08
  • SpringBoot接口中如何直接返回圖片數(shù)據(jù)

    SpringBoot接口中如何直接返回圖片數(shù)據(jù)

    這篇文章主要介紹了SpringBoot接口中如何直接返回圖片數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 重新認識Java中的ThreadLocal

    重新認識Java中的ThreadLocal

    ThreadLocal是JDK包提供的,它提供線程本地變量,如果創(chuàng)建一個ThreadLocal變量,那么訪問這個變量的每個線程都會有這個變量的一個副本,在實際多線程操作的時候,操作的是自己本地內存中的變量,從而規(guī)避了線程安全問題
    2021-05-05
  • 高并發(fā)環(huán)境下安全修改同一行數(shù)據(jù)庫數(shù)據(jù)的策略分享

    高并發(fā)環(huán)境下安全修改同一行數(shù)據(jù)庫數(shù)據(jù)的策略分享

    隨著互聯(lián)網(wǎng)技術的發(fā)展,越來越多的應用需要在高并發(fā)環(huán)境中運行,數(shù)據(jù)庫的并發(fā)控制成為了業(yè)務的關鍵,本文將介紹如何在高并發(fā)情況下,安全地修改數(shù)據(jù)庫中的同一行數(shù)據(jù),需要的可以參考一下
    2023-06-06
  • Java比較問題詳細分析

    Java比較問題詳細分析

    本篇文章主要給大家講解了Java中比較問題的相關知識,一起參考學習下吧。
    2017-12-12
  • JAVA實現(xiàn)生成順序ID,不浪費ID

    JAVA實現(xiàn)生成順序ID,不浪費ID

    這篇文章主要介紹了JAVA實現(xiàn)生成順序ID,不浪費ID問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • SpringBoot攔截器如何獲取http請求參數(shù)

    SpringBoot攔截器如何獲取http請求參數(shù)

    這篇文章主要給大家介紹了SpringBoot攔截器如何獲取http請求參數(shù)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • JDK10新特性之var泛型和多個接口實現(xiàn)方法

    JDK10新特性之var泛型和多個接口實現(xiàn)方法

    這篇文章主要介紹了JDK10的新特性:var泛型和多個接口實現(xiàn)方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05

最新評論

浦县| 临夏县| 诏安县| 含山县| 原阳县| 枣阳市| 宣恩县| 大渡口区| 湘阴县| 慈利县| 新密市| 英山县| 鄂尔多斯市| 兴隆县| 德令哈市| 枣庄市| 肥西县| 岢岚县| 宁陕县| 平邑县| 香港| 深圳市| 丰县| 罗江县| 杭州市| 广汉市| 澳门| 崇左市| 临邑县| 大关县| 衡水市| 肥城市| 泾川县| 丽水市| 衡南县| 宁陕县| 利辛县| 泸定县| 普定县| 高平市| 密山市|