vue3-elementplus-springboot驗證碼

image.png
前端
<template>
  <el-form 
    :inline="true" 
    ref="ruleFormRef" 
    :model="ruleForm" 
    status-icon 
    :rules="rules" 
    label-width="120px"
    class="demo-ruleForm">
    <!-- 驗證碼輸入框 -->
    <el-form-item label="驗證碼" prop="verifiCode">
      <el-input v-model="ruleForm.verifiCode" type="text" autocomplete="off" />
    </el-form-item>
    <!-- 驗證碼圖片 -->
    <el-form-item>
      <el-image style="width: 130px; height: 33px" @click="getVerifiCode" :src="url" />
    </el-form-item>
    <!-- 按鈕 -->
    <el-form-item>
      <el-button type="primary" @click="submitForm(ruleFormRef)">提交</el-button>
      <el-button @click="resetForm(ruleFormRef)">重置</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
    import { reactive, ref } from 'vue'
    import { FormInstance } from 'element-plus'
    import axios from 'axios'
    //前端必須設置此項,后臺session才能獲取到值
    axios.defaults.withCredentials = true;

    const ruleFormRef = ref(FormInstance)

    //記錄前端輸入的驗證碼變量
    const ruleForm = reactive({
      verifiCode: '',
    })

    //頁面加載時獲取圖片
    const url = ref('http://localhost:8089/getVerifiCode')

    //點擊圖片時獲取新驗證碼
    const getVerifiCode = () => {
      //讓參數隨機可切換驗證碼(重新生成,避免瀏覽器緩存)
      url.value = 'http://localhost:8089/getVerifiCode?' + new Date().getTime();
    }


    const checkVerifiCode = (rule, value, callback) => {
      if (!value) {
        return callback(new Error('請輸入驗證碼'))
      } else {
        //驗證碼不為空時去后臺驗證
        axios.post('http://localhost:8089/checkVerifiCode?verifiCode=' + ruleForm.verifiCode).then((res) => {
          if (res.data == "error") {
            return callback(new Error('驗證碼錯誤'))
          }else{
            callback()
          }
        })
      } 
    }

    
    //校驗
    const rules = reactive({
      verifiCode: [{ validator: checkVerifiCode }]
    })
    //提交
    const submitForm = (formEl) => {
      if (!formEl) return
      formEl.validate((valid) => {
        if (valid) {
          alert('提交成功')
        } else {
          alert('提交失敗')
          return false
        }
      })
    }
    //重置
    const resetForm = (formEl) => {
      if (!formEl) return
      formEl.resetFields()
    }
</script>

后端依賴pom.xml
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.3.RELEASE</version>
  </parent>
  <dependencies> 
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  </dependencies>
后端controller
package com.xx.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.OutputStream;
 @Controller
public class CodeController {



    @ResponseBody
    @RequestMapping("/checkVerifiCode")
    public String checkVerifiCode(String verifiCode, HttpServletRequest request )  {
        //獲取session中的驗證碼字符串
        String code  = (String) request.getSession().getAttribute("verificode");
        if(code.equals(verifiCode)) {
            return "ok" ;
        }else {
            return "error" ;
        }
    }

    //獲取驗證碼
    @ResponseBody
    @RequestMapping("/getVerifiCode")
    public String getVerifiCode(HttpServletRequest request, HttpServletResponse response) throws IOException {

        final int width = 200;           // 圖片寬度
        final int height = 100;          // 圖片高度
        final String imgType = "jpeg";   // 指定圖片格式 (不是指MIME類型)
        // 獲得 當前請求 對應的 會話對象(需要在輸出流之前創(chuàng)建)
        HttpSession session = request.getSession();
        // 獲得可以向客戶端返回圖片的輸出流
        final OutputStream output = response.getOutputStream();
        // 創(chuàng)建驗證碼圖片并返回圖片上的字符串
        String code = GraphicHelper.create(width, height, imgType, output);

        // 存儲到當前會話對象的屬性中
        session.setAttribute("verificode", code);
        //返回驗證碼(字符串)
        return code;
    }
}

驗證碼工具類
public class GraphicHelper { 
    /**
     * 以字符串形式返回生成的驗證碼迈喉,同時輸出一個圖片
     * 
     * @param width   圖片的寬度
     * @param height  圖片的高度
     * @param imgType 圖片的類型
     * @param output  圖片的輸出流(圖片將輸出到這個流中)
     * @return 返回所生成的驗證碼(字符串)
     */
    public static String create(final int width, final int height, final String imgType, OutputStream output) {
        StringBuffer sb = new StringBuffer();
        Random random = new Random();

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics graphic = image.getGraphics();

        graphic.setColor(Color.getColor("F8F8F8"));
        graphic.fillRect(0, 0, width, height);

        Color[] colors = new Color[] { Color.BLUE, Color.GRAY, Color.GREEN, Color.RED, Color.BLACK, Color.ORANGE,
                Color.CYAN };
        // 在 "畫板"上生成干擾線條 ( 50 是線條個數)
        for (int i = 0; i < 50; i++) {
            graphic.setColor(colors[random.nextInt(colors.length)]);
            final int x = random.nextInt(width);
            final int y = random.nextInt(height);
            final int w = random.nextInt(20);
            final int h = random.nextInt(20);
            final int signA = random.nextBoolean() ? 1 : -1;
            final int signB = random.nextBoolean() ? 1 : -1;
            graphic.drawLine(x, y, x + w * signA, y + h * signB);
        }

        // 在 "畫板"上繪制字母
        graphic.setFont(new Font("Comic Sans MS", Font.BOLD, 50));
        for (int i = 0; i < 6; i++) {
            final int temp = random.nextInt(26) + 97;
            String s = String.valueOf((char) temp);
            sb.append(s);
            graphic.setColor(colors[random.nextInt(colors.length)]);
            graphic.drawString(s, i * (width / 6), height - (height / 3));
        }
        graphic.dispose();
        try {
            ImageIO.write(image, imgType, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

}

注意:后端配置類設置:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) { 
        registry.addMapping("/**")
            .allowedOrigins("*")
            .allowCredentials(true)
            .allowedMethods("*")
            .allowedHeaders("*")
            .maxAge(36000);
    }
}
或者后端濾過器設置
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
response.setHeader("Access-Control-Allow-Credentials","true");  //這個很重要
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));  //這塊不能直接寫 "*"
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH"); 

前端axios應設置:

axios.defaults.withCredentials=true;
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末锤窑,一起剝皮案震驚了整個濱河市稚字,隨后出現的幾起案子吠架,更是在濱河造成了極大的恐慌怀薛,老刑警劉巖落萎,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異仆嗦,居然都是意外死亡辉阶,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門瘩扼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谆甜,“玉大人,你說我怎么就攤上這事集绰」嫒瑁” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵栽燕,是天一觀的道長罕袋。 經常有香客問我,道長碍岔,這世上最難降的妖魔是什么浴讯? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮蔼啦,結果婚禮上榆纽,老公的妹妹穿的比我還像新娘。我一直安慰自己捏肢,他們只是感情好奈籽,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鸵赫,像睡著了一般衣屏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奉瘤,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天勾拉,我揣著相機與錄音煮甥,去河邊找鬼盗温。 笑死藕赞,一個胖子當著我的面吹牛,可吹牛的內容都是我干的卖局。 我是一名探鬼主播斧蜕,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼砚偶!你這毒婦竟也來了批销?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤染坯,失蹤者是張志新(化名)和其女友劉穎均芽,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體单鹿,經...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡掀宋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了仲锄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片劲妙。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖儒喊,靈堂內的尸體忽然破棺而出镣奋,到底是詐尸還是另有隱情,我是刑警寧澤怀愧,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布侨颈,位于F島的核電站,受9級特大地震影響芯义,放射性物質發(fā)生泄漏肛搬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一毕贼、第九天 我趴在偏房一處隱蔽的房頂上張望温赔。 院中可真熱鬧,春花似錦鬼癣、人聲如沸陶贼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拜秧。三九已至,卻和暖如春章郁,著一層夾襖步出監(jiān)牢的瞬間枉氮,已是汗流浹背志衍。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留聊替,地道東北人楼肪。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像惹悄,于是被迫代替她去往敵國和親春叫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內容