前后端分离,登录验证码 实现过程 梳理
写在之前:之前自己写了一个简单的系统,最近几天完善了登录验证码的功能,现在就分享下实现过程
框架使用了springboot+vue,
逻辑分析
1.前端登录页面发起获取验证码图片请求.
2.服务端收到请求后,生成一个唯一id,对应的验证码图片 以及验证码图片对应的值(这个值使用缓存保存,id-值一一对应,缓存可使用redis或本地缓存,本地缓存适用于单节点服务)、然后把id 和图片返回前端.
3.前端收到id后保存到登录表单, 收到的图片直接展示到 登录页面
4.用户输入用户信息和 对应图片的验证码 和之前拿到的id发起登录请求
5.后端收到请求后,使用id获取缓存中真实的验证码值,然后和用户提交的验证码进行比较,如果相等则认为通过 反之不通过
注意点: 在登录成功后需要将对应id中的缓存值remove掉 防止攻击
实现步骤
第一步引入pom:
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>1.6.2</version>
</dependency>
第二步,主要代码
/**
* 依据配置信息生产验证码 LoginProperties 可以用配置bean的方式初始化,也可以在调用时自己初始化,里面都是一些验证码的基本参数这里就不展示了
* length的长度代表生成验证码内容的个数一般是四个
* @param properties
* @return
*/
private Captcha switchCaptcha(LoginProperties properties)throws Exception {
Captcha captcha = null;
synchronized (this) {
switch (properties.getCodeType()) {
case ARITHMETIC:
//算数类型
captcha = new ArithmeticCaptcha(properties.getWidth(), properties.getHeight(), properties.getLength());
break;
case CHINESE:
//中文
captcha = new ChineseCaptcha(properties.getWidth(), properties.getHeight(), properties.getLength());
break;
case CHINESE_GIF:
//中文闪图
captcha = new ChineseGifCaptcha(properties.getWidth(), properties.getHeight(), properties.getLength());
break;
case GIF:
//字母数字闪图
captcha = new GifCaptcha(properties.getWidth(), properties.getHeight(), properties.getLength());
break;
case SPEC:
//字母数字
captcha = new SpecCaptcha(properties.getWidth(), properties.getHeight(), properties.getLength());
break;
default:
System.out.println("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
}
}
//设置默认内置字体
captcha.setFont(Captcha.FONT_1);
return captcha;
}
返回验证码
//验证码内容
String captchaValue = captcha.text();
//验证码图片base64url 可直接放在前端<img>标签的 :src中展示
string img = captcha.toBase64()
前端代码:
<el-row :gutter="22">
<el-col :span="18">
<el-form-item label="" prop="loginCode">
<el-input prefix-icon="el-icon-message-solid" type="text" placeholder="验证码" v-model="user.loginCode" @keyup.enter.native="submitForm('userForm')"></el-input>
</el-form-item>
</el-col>
<el-col :span="4">
<img :src="img" @click="createCode()">
</el-col>
</el-row>
//调用验证码方法
methods: {
createCode() {
//创建验证码
this.$axios.get("/**/**").then(res => {
if (res.data.status === 0) {
this.user.loginId = res.data.data.id;
this.img = res.data.data.img;
}
});
}
}
效果展示: