springboot+vue 实现登录验证码

           这期文章我将给你们介绍登录验证码功能,如果对这个领域感兴趣,可以继续往下看看。

一、引入依赖

     <!-- easy-captcha 验证码-->
        <dependency>
            <groupId>com.github.whvcse</groupId>
            <artifactId>easy-captcha</artifactId>
            <version>1.6.2</version>
        </dependency>

二、创建CaptureConfig类

这个CaptureConfig类可能被设计为一个配置管理器,用于在整个应用程序中存储和共享配置键值对。例如,应用程序的其他部分可以通过CaptureConfig.CAPTURE_MAP来存取配置信息。这种设计模式允许配置信息集中管理,易于维护和更新。

package com.example.demo.common;

import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public   class  CaptureConfig {

    public static Map<String,String> CAPTURE_MAP = new HashMap<>();

}

三、 创建CaptureController类

CaptureController控制器类的主要作用是提供一个端点,用于生成验证码图像并将其发送到客户端。客户端(通常是用户的浏览器)需要用户输入验证码的答案,然后将其作为表单的一部分提交到服务器。服务器可以使用存储的验证码文本来验证用户输入的答案是否正确。

package com.example.demo.controller;

import com.example.demo.common.CaptureConfig;
import com.wf.captcha.ArithmeticCaptcha;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.utils.CaptchaUtil;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@CrossOrigin
@RestController
@RequestMapping

public class CaptureController {

    @RequestMapping("/captcha")
    public void captcha( String key, HttpServletRequest request, HttpServletResponse response) throws  Exception {
        //png类型 指定验证码的长宽以及字符的个数
//          SpecCaptcha captcha = new  SpecCaptcha(135,33,5);
//          captcha.setCharType(captcha.TYPE_NUM_AND_UPPER);
        //首先把验证码在后台保存一份,但是不能保存在session,可以存在redis,也可以存在后台的某个Map里面
//          CaptureConfig.CAPTURE_MAP.put(key,captcha.text().toLowerCase());
//          CaptchaUtil.out(captcha,request,response);


        ArithmeticCaptcha captcha = new ArithmeticCaptcha(135,33);
        captcha.setLen(4);
        captcha.getArithmeticString();
        captcha.text();
        CaptureConfig.CAPTURE_MAP.put(key,captcha.text().toLowerCase());
        CaptchaUtil.out(captcha,request,response);

    }


}

四、前端

验证码工作流程: 

  1. 加载验证码: 当组件加载时,自动生成一个随机key,并请求后端获取对应的验证码图片。
  2. 显示验证码: 在登录表单中显示验证码图片,用户需要输入图片中的验证码。
  3. 验证验证码: 用户提交登录表单时,后端会根据提交的key来验证用户输入的验证码是否正确。
  4. 更新验证码: 如果用户需要刷新验证码,可以点击验证码图片,这会触发clickImg方法,重新生成key并加载新的验证码图片。
<template>
  <div class="login">
  <!-- <div class="backgroundimage" /> -->
    <!-- <img :src="imgSrc" width="100%" height="100%" alt="" /> -->
    <div class="form-image">
    
  </div>
    <div class="loginPart">
      <h2>登录</h2>
      <el-form :model="user" :rules="rules" ref="ruleForm" label-position="left"  @submit.native.prevent="login">
        <el-form-item label="用户名:" prop="name">
            <el-input prop="name" v-model="user.name" prefix-icon="el-icon-user" placeholder="请输入用户名 " style="width: 100%; margin-right: 10px">
            </el-input>
          </el-form-item>
          <el-form-item label="密码:" prop="pwd">
            <el-input prop="pwd" v-model="user.pwd" prefix-icon="el-icon-lock" placeholder="请输入密码 " type="password" style="width: 100%; margin-right: 10px"></el-input>
          </el-form-item>
        <el-form-item label="验证码:" prop="verCode">
            <div style="display: flex; justify-content: space-between">
            <el-input prop="verCode" v-model="user.verCode" prefix-icon="el-icon-chat-dot-round" style="width: 70%; margin-right: 10px" placeholder="请输入验证码"></el-input>
            <img :src="captchaUrl" @click="clickImg()" class="captcha-img" />
          </div>
        </el-form-item>
            
        <div>
          <el-form-item>
            <el-button type="primary" native-type="submit" style="margin-left: 180px;">登录</el-button>
          </el-form-item>
        </div>
        
        <div style="text-align: right;color: white;">
          <el-link type="warning" @click="$router.push('/register')">没有账号?去注册</el-link>
        </div>
      </el-form>
    </div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  name: 'Login',
  data() {
    return {
      // imgSrc: require('../assets/3.jpg'),
      user: {},
      rules:{
        name:[
          {required:true,message:"请输入用户名",trigger:'blur'},
          {min:2,max:5,message: '长度在2个到5个字符',trigger: 'blur'}
        ],
        pwd:[
          {required:true,message:"请输入密码",trigger:'blur'},
          {min:4,max:10,message: '长度在4个到10个字符',trigger: 'blur'}

        ],
        verCode: [
          { required: true, message: "请输入验证码", trigger: 'blur' }
        ],
      },
      key: ' ',
       captchaUrl:' ',
    };
  },
  mounted(){
      this.key=Math.random();
      this.captchaUrl= "http://localhost:8086/captcha?key=" + this.key;
  },
  methods: {
    login() {
      this.$refs['ruleForm'].validate((valid) => {
        if (valid) {
          const userData = JSON.parse(JSON.stringify(this.user));
          console.log("User before login:", userData);
          axios.post("http://localhost:8086/user/login?key=" + this.key, this.user, {
            headers: {
              'Content-Type': 'application/json' 
            }
          })
              .then(response => {
                  console.log(response)
                const res=response.data
                if (res.state===true) {
                  localStorage.setItem('id',res.user.id)
                  localStorage.setItem('role',res.user.role)
                  localStorage.setItem('name',res.user.name)
                  localStorage.setItem('pwd',res.user.pwd)
                  localStorage.setItem('sex',res.user.sex)
                  localStorage.setItem('phone',res.user.phone)
                  localStorage.setItem('email',res.user.email)
                  localStorage.setItem('token',res.token)
                  localStorage.setItem('avatarUrl',res.user.avatarUrl)
                   //在这里添加自己添加的字段比如phone和address等等,这里添加拉之后你的person.vue也可以加上
                 if(localStorage.getItem('role')){
                  axios.get("http://localhost:8086/user/menu",{
                    params:{
                      role:localStorage.getItem('role')
                    }
                  }).then(res=>{
                    console.log(res)
                    localStorage.setItem('menus',JSON.stringify(res.data) )
                    console.log(localStorage.getItem('menus'))
                    const redirectPath = localStorage.getItem('role') === '管理员' ? '/home' : '/front/home';
                    this.$router.push(redirectPath);
                    this.$message.success("欢迎进入首页");
                  })

                  }
                  
                 }
                 if(res.msg=='验证码错误'){
                  this.$message.error("验证码错误");
                 }
                 if(res.msg=='用户名或者密码错误'){
                  this.$message.error("用户名或密码错误");
                 }
              })
              .catch(error => {
                console.error("Error during login:", error);
                this.$message.error("登录失败,请重试");
                 this.key=Math.random();
                this.captchaUrl= "http://localhost:8086/captcha?key=" + this.key;
                this.user.verCode=''
              });
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    clickImg(){
        this.key=Math.random();
        this.captchaUrl= "http://localhost:8086/captcha?key=" + this.key;
    }

  }
}
 
</script>

<style>

.loginPart h2 {
  margin: 0 0 30px;
  padding: 0;
  color: rgb(0, 0, 0);
  text-align: center;
}

.loginPart .inputElement input {
  width: 100%;
  padding: 10px 0;
  font-size: 16px;
  color: rgb(4, 4, 4);
  letter-spacing: 1px;
  margin-bottom: 5px;
  border: none;
  border-bottom: 1px solid #fff;
  outline: none;
  background: transparent;
  background-color: rgba(248, 242, 242, 0.9); /* 可以进一步加深表单输入框内部背景 */
}


/* 公共Flex容器样式 */
 .login {
  display: flex;
  align-items: center; /* 垂直居中 */
  justify-content: center; /* 水平居中 */
  min-height: 100vh; /* 至少为视口高度 */
}

/* 登录和注册表单样式 */
.loginPart {
  width: 530px; /* 根据需要调整宽度 */
  padding: 50px;
  background: rgb(255, 255, 255);
  box-sizing: border-box;
  box-shadow: 0px 15px 25px rgba(0, 0, 0, .5);
  border-radius: 15px;
  margin: 0; /* 移除默认的外边距 */
  margin-left: 100px; /* 与注册表单保持一定间距 */
}

/* 图片容器样式 */
.form-image {
  width: 300px; /* 根据需要调整宽度 */
  height: 300px; /* 根据需要调整高度,与表单等高 */
  background-image: url('~@/assets/篮子.jpg');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  margin-left: 50px; /* 与表单保持一定间距 */
}

/* 将.loginPart放在右边,.form-image放在左边 */
.login {
  flex-direction: row-reverse; /* 将图片放到左边,表单放到右边 */
}

/* 其他样式保持不变 */
.loginPart .el-input__inner::placeholder {
  color: rgba(0, 0, 0, 0.564); /* 半透明的灰色,alpha值为0.5表示50%的透明度 */
}
/* 通用输入框样式 */
.el-form-item__inner .el-input__inner {
  font-size: 16px; /* 统一字体大小 */
  color: rgb(11, 11, 11); /* 统一字体颜色 */
  border: none; /* 无边框 */
  border-bottom: 1px solid #fff; /* 底部边框 */
  background: transparent; /* 背景透明 */
  background-color: rgba(248, 242, 242, 0.9); /* 半透明背景 */
  position: relative; /* 确保输入框内部的元素在同一层级 */
}

/* 占位符样式 */
.el-form-item__inner .el-input__inner::placeholder {
  color: rgba(169, 169, 169, 0.5); /* 半透明的灰色 */
}

/* 确保el-form-item垂直居中对齐 */
.el-form-item {
  display: flex;
  align-items: center; /* 垂直居中对齐 */
  margin-bottom: 10px; /* 根据需要添加外边距 */
  
}

.el-form-item__label {
  margin-right: 5px; /* 减小label与输入框之间的距离 */
}

/* 调整label的样式,确保文本左对齐并有足够的宽度 */
.el-form-item__label {
  text-align: left; /* 确保标签文本左对齐 */
  width: 100px; /* 根据需要设置label的宽度 */
  padding: 0 0 0 0; /* 移除Element UI的默认padding */
  margin-right: -40px; /* 标签和输入框之间的间距 */
  font-weight: bold;
}


/* 验证码输入框的样式,确保输入框宽度合适 */
.el-input__inner {
  width: 60%; /* 根据需要调整宽度,这里假设为60% */
}

/* 验证码图片的样式,确保图片宽度合适 */
.captcha-img {
  width: 35%; /* 根据需要调整宽度,这里假设为35% */
  height: 33px; /* 高度与输入框保持一致 */
  cursor: pointer; /* 当鼠标悬停时显示为手形图标 */
}


</style>

五、页面展示

 

 六、总结

   希望对你们有帮助,下期再见!

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用以下步骤来实现 Spring BootVue.js 登录验证码: 1. 在 Spring Boot实现验证码的生成和验证 您可以使用第三方库来生成验证码,例如 Kaptcha 或 Google 的 reCAPTCHA。使用 Kaptcha 的示例代码如下: ```java // 生成验证码 @RequestMapping("/captcha.jpg") public void captcha(HttpServletResponse response, HttpSession session) throws IOException { response.setHeader("Cache-Control", "no-store, no-cache"); response.setContentType("image/jpeg"); // 生成验证码 String text = kaptchaProducer.createText(); session.setAttribute("captcha", text); // 将验证码写入响应 BufferedImage image = kaptchaProducer.createImage(text); ServletOutputStream out = response.getOutputStream(); ImageIO.write(image, "jpg", out); out.flush(); out.close(); } // 验证码验证 @PostMapping("/login") public String login(String username, String password, String captcha, HttpSession session) { String sessionCaptcha = (String) session.getAttribute("captcha"); if (!captcha.equalsIgnoreCase(sessionCaptcha)) { return "验证码错误"; } // 其他登录逻辑 // ... } ``` 2. 在 Vue.js实现验证码的展示和刷新 您可以使用第三方库来实现验证码的展示和刷新,例如 vue-verify-code。使用 vue-verify-code 的示例代码如下: ```vue <template> <div> <input v-model="captcha" placeholder="请输入验证码"> <verify-code :url="captchaUrl" @success="onCaptchaSuccess"></verify-code> </div> </template> <script> import VerifyCode from 'vue-verify-code'; export default { components: { VerifyCode, }, data() { return { captcha: '', captchaUrl: '/captcha.jpg', }; }, methods: { onCaptchaSuccess() { // 验证码刷新成功 this.captchaUrl = '/captcha.jpg?' + Date.now(); }, }, }; </script> ``` 在上面的示例代码中,我们使用了 vue-verify-code 组件来展示验证码。该组件会在页面加载时自动请求 `/captcha.jpg` 地址来获取验证码图片。在用户输入验证码后,我们可以通过监听 `@success` 事件来刷新验证码,以便用户重新输入。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值