欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java使用hutool工具實現(xiàn)驗證碼登錄

 更新時間:2024年12月17日 10:13:48   作者:七禾頁話  
這篇文章主要為大家詳細介紹了Java如何使用hutool工具實現(xiàn)驗證碼登錄功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下

1.先說一下流程圖

2.導入工具包

<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.12</version>
        </dependency>

3.流程梳理

3.1前端模版代碼

<template>
          <form @submit.prevent="handleSubmit">
            <div class="input-group">
              <div class="captcha-wrapper">
                <input
                  v-model="form.captcha"
                  type="text"
                  placeholder="請輸入驗證碼"
                  :class="{ 'shake': formErrors.captcha }"
                  maxlength="4"
                />
                <div class="captcha-container">
                  <img 
                    :src="captchaUrl" 
                    @click="refreshCaptcha"
                    class="captcha-img"
                    alt="驗證碼"
                    @error="handleCaptchaError"
                  />
                  <button 
                    type="button" 
                    class="refresh-btn"
                    @click="refreshCaptcha"
                    title="刷新驗證碼"
                  >
                  </button>
                </div>
              </div>
              <transition name="fade">
                <p v-if="formErrors.captcha" class="error-message">{{ formErrors.captcha }}</p>
              </transition> 
</template>

3.2邏輯代碼

前端掛載組件時發(fā)送請求到后端生成驗證碼

@RestController
@RequestMapping("/api")
public class AuthController {
    @GetMapping("/captcha")
    public void generateCaptcha(HttpServletResponse response, HttpSession session) {
        // 生成驗證碼
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(100, 40);
        // 將驗證碼存入session
        session.setAttribute("captcha", lineCaptcha.getCode());

        try {
            // 輸出到客戶端
            response.setContentType("image/png");
            lineCaptcha.write(response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

<img :src="captchaUrl”>動態(tài)綁定實現(xiàn)渲染驗證碼,button綁定的是這個refreshCaptcha事件,所以可以實現(xiàn)刷新驗證碼的操作

const captchaUrl = ref('')
// 組件掛載時加載驗證碼
onMounted(() => {
  refreshCaptcha()
})
const refreshCaptcha = () => {
  // 直接使用API地址,添加時間戳防止緩存
  captchaUrl.value = `${request.defaults.baseURL}/api/captcha?t=${new Date().getTime()}`
  // 清空驗證碼輸入
  form.captcha = ''
}

然后就是前段提交數(shù)據(jù)到后端做認證

const form = reactive({
  email: '',
  password: '',
  remember: false,
  captcha: ''
})
export function login(data) {
  return request({
    url: '/api/login',
    method: 'post',
    data
  })
}
 try {
    // 發(fā)送登錄請求
    const res = await login({
      username: form.email,
      password: form.password,
      captcha: form.captcha,
      remember: form.remember
    })

后端接收數(shù)據(jù)進行校驗

   @PostMapping("/login")
    public Result login(@RequestBody LoginDTO loginDTO, HttpSession session) {
        // 獲取session中的驗證碼
        String captcha = (String) session.getAttribute("captcha");
        // 校驗驗證碼
        if (!loginDTO.getCaptcha().equalsIgnoreCase(captcha)) {
            return Result.error("驗證碼錯誤");
        }
        // TODO: 進行登錄邏輯處理
        return null;
    }

4.前端所有代碼

<template>
  <div class="login-page">
    <div class="login-container">
      <!-- Left side with rocket -->
      <div class="left-side">
        <div class="logo-container">
          <h1 class="logo">七禾頁話</h1>
        </div>
        
        <div class="hero-text">
          <h2>歡迎使用<br />學生管理系統(tǒng)</h2>
          <p>讓工作更高效!</p>
        </div>

        <!-- Animated rocket -->
        <div class="rocket-container">
          <div class="rocket" :class="{ 'rocket-hover': isRocketHovering }">
            <div class="rocket-body">
              <div class="rocket-main"></div>
              <div class="rocket-base"></div>
              <div class="rocket-side-left"></div>
              <div class="rocket-side-right"></div>
            </div>
          </div>
          
          <!-- Animated clouds -->
          <div class="clouds">
            <div v-for="i in 3" :key="i" 
                 class="cloud"
                 :class="`cloud-${i}`"
                 :style="`--delay: ${i * 2}s`">
            </div>
          </div>
        </div>
      </div>

      <!-- Right side with form -->
      <div class="right-side">
        <div class="form-container">
          <h2>用戶登錄</h2>
          
          <form @submit.prevent="handleSubmit">
            <div class="input-group">
              <input
                v-model="form.email"
                type="email"
                placeholder="請輸入用戶名"
                :class="{ 'shake': formErrors.email }"
              />
              <transition name="fade">
                <p v-if="formErrors.email" class="error-message">{{ formErrors.email }}</p>
              </transition>
            </div>

            <div class="input-group">
              <input
                v-model="form.password"
                type="password"
                placeholder="請輸入密碼"
                :class="{ 'shake': formErrors.password }"
              />
              <transition name="fade">
                <p v-if="formErrors.password" class="error-message">{{ formErrors.password }}</p>
              </transition>
            </div>

            <div class="input-group">
              <div class="captcha-wrapper">
                <input
                  v-model="form.captcha"
                  type="text"
                  placeholder="請輸入驗證碼"
                  :class="{ 'shake': formErrors.captcha }"
                  maxlength="4"
                />
                <div class="captcha-container">
                  <img 
                    :src="captchaUrl" 
                    @click="refreshCaptcha"
                    class="captcha-img"
                    alt="驗證碼"
                    @error="handleCaptchaError"
                  />
                  <button 
                    type="button" 
                    class="refresh-btn"
                    @click="refreshCaptcha"
                    title="刷新驗證碼"
                  >
                    <svg viewBox="0 0 24 24" class="refresh-icon">
                      <path d="M17.65 6.35A7.958 7.958 0 0012 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0112 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" fill="currentColor"/>
                    </svg>
                  </button>
                </div>
              </div>
              <transition name="fade">
                <p v-if="formErrors.captcha" class="error-message">{{ formErrors.captcha }}</p>
              </transition>
            </div>

            <div class="remember-me">
              <input
                v-model="form.remember"
                type="checkbox"
                id="remember"
              />
              <label for="remember">記住我</label>
            </div>

            <button
              type="submit"
              :class="{ 'loading': isLoading }"
              :disabled="isLoading"
            >
              <span v-if="!isLoading">登 錄</span>
              <span v-else class="loading-text">
                <svg class="spinner" viewBox="0 0 50 50">
                  <circle class="path" cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
                </svg>
                登錄中...
              </span>
            </button>
          </form>

          <div class="auth-links">
            <p class="forgot-password">
              <a href="#">忘記密碼?</a>
            </p>
            <p class="register-link">
              還沒有賬號? <router-link to="/register" class="text-primary">立即注冊</router-link>
            </p>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { login, getCaptcha } from '@/api/auth'
import request from '@/utils/request'

const router = useRouter()
const isRocketHovering = ref(true)
const isLoading = ref(false)
const captchaUrl = ref('')

const form = reactive({
  email: '',
  password: '',
  remember: false,
  captcha: ''
})

const formErrors = reactive({
  email: '',
  password: '',
  captcha: ''
})

// 刷新驗證碼
const refreshCaptcha = () => {
  // 直接使用API地址,添加時間戳防止緩存
  captchaUrl.value = `${request.defaults.baseURL}/api/captcha?t=${new Date().getTime()}`
  // 清空驗證碼輸入
  form.captcha = ''
}

// 處理驗證碼加載錯誤
const handleCaptchaError = () => {
  console.error('驗證碼圖片加載失敗')
  // 可以在這里添加重試邏輯或顯示錯誤提示
}

// 組件掛載時加載驗證碼
onMounted(() => {
  refreshCaptcha()
})

const handleSubmit = async () => {
  // Reset errors
  formErrors.email = ''
  formErrors.password = ''
  formErrors.captcha = ''

  // Validate
  if (!form.email) {
    formErrors.email = '請輸入用戶名'
    return
  }
  if (!form.password) {
    formErrors.password = '請輸入密碼'
    return
  }
  if (!form.captcha) {
    formErrors.captcha = '請輸入驗證碼'
    return
  }

  // Show loading state
  isLoading.value = true

  try {
    // 發(fā)送登錄請求
    const res = await login({
      username: form.email,
      password: form.password,
      captcha: form.captcha,
      remember: form.remember
    })

    // 存儲 token
    localStorage.setItem('token', res.data.token)
    
    // 登錄成功,跳轉(zhuǎn)到首頁
    router.push('/dashboard')
  } catch (error) {
    // 根據(jù)錯誤類型顯示不同的錯誤信息
    if (error.code === 400) {
      formErrors.captcha = '驗證碼錯誤'
      await refreshCaptcha()
    } else if (error.code === 401) {
      formErrors.password = '用戶名或密碼錯誤'
      await refreshCaptcha()
    } else {
      console.error('登錄失敗:', error)
      formErrors.password = error.message || '登錄失敗,請稍后重試'
      await refreshCaptcha()
    }
  } finally {
    // Reset loading state
    isLoading.value = false
  }
}

// Start rocket hover animation
setInterval(() => {
  isRocketHovering.value = !isRocketHovering.value
}, 2000)
</script>

5.后端代碼

package com.qiheyehua.vuespringboot2.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.qiheyehua.vuespringboot2.domain.dto.LoginDTO;
import com.qiheyehua.vuespringboot2.utils.Result;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;

/**
 * @author 七禾頁話
 * @date 2024/12/16 18:57
 **/
@RestController
@RequestMapping("/api")
public class AuthController {
    @GetMapping("/captcha")
    public void generateCaptcha(HttpServletResponse response, HttpSession session) {
        // 生成驗證碼
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(100, 40);
        // 將驗證碼存入session
        session.setAttribute("captcha", lineCaptcha.getCode());

        try {
            // 輸出到客戶端
            response.setContentType("image/png");
            lineCaptcha.write(response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @PostMapping("/login")
    public Result login(@RequestBody LoginDTO loginDTO, HttpSession session) {
        // 獲取session中的驗證碼
        String captcha = (String) session.getAttribute("captcha");
        // 校驗驗證碼
        if (!loginDTO.getCaptcha().equalsIgnoreCase(captcha)) {
            return Result.error("驗證碼錯誤");
        }
        // TODO: 進行登錄邏輯處理
        return null;
    }
}

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

相關(guān)文章

  • 測試環(huán)境頻繁Full GC問題的解決思路分析

    測試環(huán)境頻繁Full GC問題的解決思路分析

    全文介紹了作者通過與調(diào)用方交互,發(fā)現(xiàn)welink-front服務不可用的問題,通過jmap-heap和jstat-gccause命令,作者找到了問題的原因是元數(shù)據(jù)區(qū)內(nèi)存使用率過高,觸發(fā)了FullGC,作者通過分析GC日志和堆內(nèi)存使用情況,確定了問題的根本原因
    2025-01-01
  • Java導出Excel通用工具類實例代碼

    Java導出Excel通用工具類實例代碼

    這篇文章主要給大家介紹了關(guān)于Java導出Excel通用工具類的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • Java Spring MVC獲取請求數(shù)據(jù)詳解操作

    Java Spring MVC獲取請求數(shù)據(jù)詳解操作

    Spring MVC 是 Spring 提供的一個基于 MVC 設(shè)計模式的輕量級 Web 開發(fā)框架,本質(zhì)上相當于 Servlet,Spring MVC 角色劃分清晰,分工明細。由于 Spring MVC 本身就是 Spring 框架的一部分,可以說和 Spring 框架是無縫集成
    2021-11-11
  • 一文弄懂Java中ThreadPoolExecutor

    一文弄懂Java中ThreadPoolExecutor

    ThreadPoolExecutor是Java中的一個線程池實現(xiàn),它可以管理和控制多個 Worker Threads,本文就詳細的介紹一下Java中ThreadPoolExecutor,具有一定的參考價值,感興趣的可以了解一下
    2023-08-08
  • 利用Java實現(xiàn)圖片轉(zhuǎn)化為ASCII圖的示例代碼

    利用Java實現(xiàn)圖片轉(zhuǎn)化為ASCII圖的示例代碼

    本文將詳細講解如何利用 Java 實現(xiàn)圖片轉(zhuǎn)化為 ASCII 圖,從項目背景與意義、相關(guān)技術(shù)知識,到系統(tǒng)需求與架構(gòu)設(shè)計,再到詳細實現(xiàn)思路、完整代碼和代碼解讀,最后對項目進行總結(jié)與展望,需要的朋友可以參考下
    2025-03-03
  • java構(gòu)建OAuth2授權(quán)服務器

    java構(gòu)建OAuth2授權(quán)服務器

    本文主要介紹了java構(gòu)建OAuth2授權(quán)服務器,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2021-07-07
  • 深入理解Java中的WeakHashMap

    深入理解Java中的WeakHashMap

    這篇文章主要介紹了深入理解Java中的WeakHashMap,WeakHashMap從名字可以得知主要和Map有關(guān),不過還有一個Weak,我們就更能自然而然的想到這里面還牽扯到一種弱引用結(jié)構(gòu),因此想要徹底搞懂,我們還需要知道四種引用,需要的朋友可以參考下
    2023-09-09
  • SpringBoot開啟虛擬線程的實現(xiàn)流程

    SpringBoot開啟虛擬線程的實現(xiàn)流程

    虛擬線程(Virtual?Thread)也稱協(xié)程或纖程,是一種輕量級的線程實現(xiàn),與傳統(tǒng)的線程以及操作系統(tǒng)級別的線程(也稱為平臺線程)相比,它的創(chuàng)建開銷更小、資源利用率更高,本文給大家介紹了SpringBoot如何開啟虛擬線程,需要的朋友可以參考下
    2024-06-06
  • 超詳細講解SpringCloud?Commons公共抽象的用法

    超詳細講解SpringCloud?Commons公共抽象的用法

    這篇文章主要介紹了超詳細講解SpringCloud?Commons公共抽象的用法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 詳細了解MyBatis的異常處理機制

    詳細了解MyBatis的異常處理機制

    本文將對MyBatis的異常體系以及異常使用進行學習,MyBatis版本是3.5.6,作為一款成熟的ORM框架,MyBatis有自己一套成熟的異常處理體系,,需要的朋友可以參考下
    2023-06-06

最新評論