vue3-elementplus-springboot验证码

2023-01-05  本文已影响0人  晓晓_1931
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类型)
        // 获得 当前请求 对应的 会话对象(需要在输出流之前创建)
        HttpSession session = request.getSession();
        // 获得可以向客户端返回图片的输出流
        final OutputStream output = response.getOutputStream();
        // 创建验证码图片并返回图片上的字符串
        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;
上一篇下一篇

猜你喜欢

热点阅读