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

SpringBoot使用easy-captcha 實(shí)現(xiàn)驗(yàn)證碼登錄功能(解決思路)

 更新時(shí)間:2025年02月08日 09:57:32   作者:八月五  
文章介紹了如何使用Spring Boot和Easy-Captcha實(shí)現(xiàn)驗(yàn)證碼登錄功能,后端通過(guò)Easy-Captcha生成驗(yàn)證碼并存儲(chǔ)在Redis中,前端獲取驗(yàn)證碼并顯示給用戶(hù),登錄時(shí),前端將用戶(hù)輸入的驗(yàn)證碼和標(biāo)識(shí)符發(fā)送到后端進(jìn)行驗(yàn)證,感興趣的朋友跟隨小編一起看看吧

一、 環(huán)境準(zhǔn)備

1. 解決思路

  • 后端使用 easy-captcha 創(chuàng)建驗(yàn)證碼對(duì)象。
  • 將驗(yàn)證碼文本存儲(chǔ)到 Redis 中,并生成一個(gè)隨機(jī)的 key。
  • 將驗(yàn)證碼的 Base64 字符串和 key 返回給前端。
  • 前端通過(guò) Base64 字符串顯示驗(yàn)證碼圖片,并將 key 保存起來(lái)。
  • 登錄時(shí),前端將用戶(hù)輸入的驗(yàn)證碼和 key 發(fā)送到后端。
  • 后端通過(guò) key 從 Redis 中獲取驗(yàn)證碼文本,并進(jìn)行比對(duì)驗(yàn)證。

2. 接口文檔

URL

GET /captcha

參數(shù)

無(wú)

返回

{
    "msg": "操作成功",
    "code": 200,
    "data": {
      "uuid": "b71fafb1a91b4961afb27372bd3af77c",
      "captcha": "data:image/png;base64,iVBORw0KGgoAAAA",
      "code": "nrew"
    }
}

3. redis下載

見(jiàn) redis安裝配置教程

二、后端實(shí)現(xiàn)

1. 引入依賴(lài)

在 pom.xml 文件中引入 easy-captchaRedis 相關(guān)依賴(lài):

<dependency>
    <groupId>com.github.whvcse</groupId>
    <artifactId>easy-captcha</artifactId>
    <version>1.6.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2. 添加配置

application.yml里添加連接redis數(shù)據(jù)庫(kù)的配置信息:

spring:
  redis:
    open: true
    database: 1
    host: localhost
    port: 6379

3. 后端代碼實(shí)現(xiàn)

controller:

@RestController
public class LoginController {
    @Autowired
    private RedisTemplate redisTemplate;
    @GetMapping("/captcha")
	public Result captcha() {
	    // 創(chuàng)建一個(gè) SpecCaptcha 對(duì)象,設(shè)置驗(yàn)證碼圖片的寬度、高度和字符長(zhǎng)度
	    SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 4);
	    // 生成驗(yàn)證碼文本,并將其轉(zhuǎn)換為小寫(xiě)(方便后續(xù)比較,忽略大小寫(xiě))
	    String code = specCaptcha.text().toLowerCase();
	    // 生成一個(gè)唯一的 UUID,用于存儲(chǔ)驗(yàn)證碼到 Redis 中
	    String uuid = IdUtil.simpleUUID();
	    // 將驗(yàn)證碼文本存入 Redis,并設(shè)置過(guò)期時(shí)間為 2 分鐘(120 秒)
	    // 這樣可以確保驗(yàn)證碼在一定時(shí)間后自動(dòng)失效,避免被惡意利用
	    this.redisTemplate.opsForValue().set(uuid, code, 120, TimeUnit.SECONDS);
	    // 創(chuàng)建一個(gè) Map,用于存儲(chǔ)返回給前端的數(shù)據(jù)
	    Map<String, String> map = new HashMap<String, String>(3);
	    // 將 UUID 存入 Map,前端需要將這個(gè) UUID 一起發(fā)送到后端進(jìn)行驗(yàn)證
	    map.put("uuid", uuid);
	    // 將生成的驗(yàn)證碼文本存入 Map(可選,通常前端不需要知道驗(yàn)證碼文本)
	    map.put("code", code);
	    // 將驗(yàn)證碼圖片轉(zhuǎn)換為 Base64 字符串,并存入 Map
	    // 前端可以通過(guò)這個(gè) Base64 字符串生成驗(yàn)證碼圖片
	    map.put("captcha", specCaptcha.toBase64());
	    // 返回 Result 對(duì)象,其中包含驗(yàn)證碼圖片的 Base64 字符串和 UUID
	    // Result.ok() 表示操作成功,put("data", map) 將 Map 數(shù)據(jù)放入響應(yīng)中
	    return Result.ok().put("data", map);
	}
	@PostMapping("/login")
    public Result login(@RequestBody LoginForm loginForm, HttpSession session){
        //驗(yàn)證碼校驗(yàn)
        String code = (String) this.redisTemplate.opsForValue().get(loginForm.getUuid());
        //判斷驗(yàn)證碼是否有效
        if(code == null){
            return Result.error("驗(yàn)證碼已過(guò)期");
        }
        //判斷驗(yàn)證碼是否正確
        if(!code.equals(loginForm.getCaptcha())){
            return Result.error("驗(yàn)證碼錯(cuò)誤");
        }
        //判斷用戶(hù)名是否正確
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", loginForm.getUsername());
        User user = this.userService.getOne(queryWrapper);
        if(user == null){
            return Result.error("用戶(hù)名錯(cuò)誤");
        }
        //判斷密碼是否正確
        String password = SecureUtil.sha256(loginForm.getPassword());
        if(!password.equals(user.getPassword())){
            return Result.error("密碼錯(cuò)誤");
        }
        //驗(yàn)證用戶(hù)是否可用
        if(user.getStatus() == 0) {
            return Result.error("賬號(hào)已被鎖定,請(qǐng)聯(lián)系管理員");
        }
        //登錄成功
        session.setAttribute("user", user);
        //創(chuàng)建token
        String token = this.jwtUtil.createToken(String.valueOf(user.getUserId()));
        this.redisTemplate.opsForValue().set("communityuser-"+user.getUserId(), token,jwtUtil.getExpire());
        Map<String,Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtil.getExpire());
        LogAspect.user = user;
        return Result.ok().put("data", map);
    }
}

RedisTemplate 是 Spring Data Redis 提供的一個(gè)高級(jí)抽象,封裝了 Redis 的操作。它支持多種數(shù)據(jù)結(jié)構(gòu)(如字符串、列表、集合、哈希等),并提供了豐富的操作方法。通過(guò) RedisTemplate,可以方便地執(zhí)行 Redis 命令,而無(wú)需直接使用 Redis 的原生客戶(hù)端。

常用方法

  • opsForValue():用于操作 Redis 中的字符串(String)數(shù)據(jù)。
  • opsForList():用于操作 Redis 中的列表(List)數(shù)據(jù)。
  • opsForSet():用于操作 Redis 中的集合(Set)數(shù)據(jù)。
  • opsForHash():用于操作 Redis 中的哈希(Hash)數(shù)據(jù)。
  • opsForZSet():用于操作 Redis 中的有序集合(Sorted Set)數(shù)據(jù)。

4. 前端代碼實(shí)現(xiàn)

獲取驗(yàn)證碼
前端通過(guò)調(diào)用后端接口獲取驗(yàn)證碼圖片和 UUID。這個(gè) UUID 用于在后端標(biāo)識(shí)驗(yàn)證碼的唯一性。

// 獲取驗(yàn)證碼
getCaptcha() {
  getCaptchaImg().then(res => {
    this.captchaPath = res.data.captcha; // 將驗(yàn)證碼圖片的 Base64 字符串賦值給 captchaPath
    this.loginForm.uuid = res.data.uuid; // 將 UUID 賦值給 loginForm 的 uuid 屬性
    if (process.env.NODE_ENV === 'development') {
      this.loginForm.captcha = res.data.code; // 在開(kāi)發(fā)環(huán)境中自動(dòng)填充驗(yàn)證碼(方便測(cè)試)
    }
  });
}

顯示驗(yàn)證碼
前端通過(guò) el-image 組件顯示驗(yàn)證碼圖片,并提供點(diǎn)擊刷新功能。

<el-image
  class="captcha-img"
  :src="captchaPath" <!-- 綁定驗(yàn)證碼圖片的 Base64 字符串 -->
  @click="getCaptcha()" <!-- 點(diǎn)擊圖片時(shí)重新獲取驗(yàn)證碼 -->
/>

3. 提交表單時(shí)驗(yàn)證驗(yàn)證碼
用戶(hù)輸入驗(yàn)證碼后,點(diǎn)擊登錄按鈕提交表單。前端將用戶(hù)輸入的驗(yàn)證碼和 UUID 一起發(fā)送到后端進(jìn)行驗(yàn)證。

handleLogin() {
  this.$refs.loginForm.validate(valid => {
    if (valid) {
      this.loading = true;
      this.$store.dispatch('user/login', this.loginForm)
        .then(() => {
          this.$router.push({ path: this.redirect || '/' }); // 登錄成功后跳轉(zhuǎn)
        })
        .catch(() => {
          this.getCaptcha(); // 登錄失敗,重新獲取驗(yàn)證碼
          this.loading = false;
        });
    } else {
      return false;
    }
  });
}

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

相關(guān)文章

  • SpringBoot服務(wù)器端解決跨域問(wèn)題

    SpringBoot服務(wù)器端解決跨域問(wèn)題

    這篇文章主要介紹了SpringBoot服務(wù)器端解決跨域問(wèn)題,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下
    2020-11-11
  • 教你如何用Eclipse創(chuàng)建一個(gè)Maven項(xiàng)目

    教你如何用Eclipse創(chuàng)建一個(gè)Maven項(xiàng)目

    這篇文章主要介紹了教你如何用Eclipse創(chuàng)建一個(gè)Maven項(xiàng)目,文中有非常詳細(xì)的代碼示例,對(duì)正在入門(mén)Java的小伙伴們是非常有幫助的喲,需要的朋友可以參考下
    2021-05-05
  • Java并發(fā)之Condition案例詳解

    Java并發(fā)之Condition案例詳解

    這篇文章主要介紹了Java并發(fā)之Condition案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • Java中線程Thread的特點(diǎn)及使用

    Java中線程Thread的特點(diǎn)及使用

    這篇文章主要介紹了Java中線程的特點(diǎn)及使用,線程是進(jìn)程的組成部分,一個(gè)進(jìn)程可以擁有多個(gè)線程,而一個(gè)線程必須擁有一個(gè)父進(jìn)程,那么線程該如何使用,讓我們一起來(lái)看看吧
    2023-04-04
  • springboot+jwt實(shí)現(xiàn)token登陸權(quán)限認(rèn)證的實(shí)現(xiàn)

    springboot+jwt實(shí)現(xiàn)token登陸權(quán)限認(rèn)證的實(shí)現(xiàn)

    這篇文章主要介紹了springboot+jwt實(shí)現(xiàn)token登陸權(quán)限認(rèn)證的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • String類(lèi)型轉(zhuǎn)localDate,date轉(zhuǎn)localDate的實(shí)現(xiàn)代碼

    String類(lèi)型轉(zhuǎn)localDate,date轉(zhuǎn)localDate的實(shí)現(xiàn)代碼

    這篇文章主要介紹了String類(lèi)型轉(zhuǎn)localDate,date轉(zhuǎn)localDate的實(shí)現(xiàn)代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • Java利用Jackson序列化實(shí)現(xiàn)數(shù)據(jù)脫敏詳解

    Java利用Jackson序列化實(shí)現(xiàn)數(shù)據(jù)脫敏詳解

    在項(xiàng)目中有些敏感信息不能直接展示,比如客戶(hù)手機(jī)號(hào)、身份證、車(chē)牌號(hào)等信息,展示時(shí)均需要進(jìn)行數(shù)據(jù)脫敏,防止泄露客戶(hù)隱私。本文將利用Jackson序列化實(shí)現(xiàn)數(shù)據(jù)脫敏,需要的可以參考一下
    2023-03-03
  • IDEA報(bào)錯(cuò)"Cannot?resolve?symbol"問(wèn)題的解決辦法

    IDEA報(bào)錯(cuò)"Cannot?resolve?symbol"問(wèn)題的解決辦法

    早上來(lái)了,打開(kāi)idea發(fā)現(xiàn)注解等都變紅報(bào)錯(cuò)can’t resolvesymbol,由于這個(gè)錯(cuò)之前也報(bào)過(guò),所以記錄一下,這篇文章主要給大家介紹了關(guān)于IDEA報(bào)錯(cuò)"Cannot?resolve?symbol"問(wèn)題的解決辦法,需要的朋友可以參考下
    2023-11-11
  • Java中的泛型使用詳解

    Java中的泛型使用詳解

    本文給大家介紹java中的泛型知識(shí),包括基本語(yǔ)法使用方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2025-10-10
  • Java實(shí)現(xiàn)代碼塊耗時(shí)測(cè)算工具類(lèi)

    Java實(shí)現(xiàn)代碼塊耗時(shí)測(cè)算工具類(lèi)

    這篇文章主要為大家介紹了如何利用Java語(yǔ)言編寫(xiě)一個(gè)工具類(lèi),用來(lái)測(cè)算代碼塊的耗時(shí),同時(shí)還能顯示進(jìn)度,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-05-05

最新評(píng)論

海晏县| 象山县| 古蔺县| 饶平县| 名山县| 长乐市| 乾安县| 合肥市| 云龙县| 扎赉特旗| 武强县| 太仆寺旗| 延庆县| 南召县| 监利县| 望谟县| 长沙县| 西丰县| 图木舒克市| 聊城市| 乌鲁木齐县| 府谷县| 沙坪坝区| 绵阳市| 许昌市| 莱州市| 牟定县| 富锦市| 洮南市| 阿拉尔市| 漳浦县| 紫金县| 汝城县| 正定县| 山丹县| 波密县| 苍梧县| 昭苏县| 铁力市| 贵州省| 宜兰县|