这期文章我将给你们介绍登录验证码功能,如果对这个领域感兴趣,可以继续往下看看。
一、引入依赖
<!-- 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);
}
}
四、前端
验证码工作流程:
- 加载验证码: 当组件加载时,自动生成一个随机key,并请求后端获取对应的验证码图片。
- 显示验证码: 在登录表单中显示验证码图片,用户需要输入图片中的验证码。
- 验证验证码: 用户提交登录表单时,后端会根据提交的key来验证用户输入的验证码是否正确。
- 更新验证码: 如果用户需要刷新验证码,可以点击验证码图片,这会触发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>
五、页面展示
六、总结
希望对你们有帮助,下期再见!