点击(此处)折叠或打开
-
-
-
1|0SpringBoot 版本
-
本文基于的 Spring Boot 的版本是 2.6.7 。
-
-
2|0 引入依赖
-
captcha 一款超简单的验证码生成,还挺好玩的。还有中文验证码,动态验证码. 。在项目中 pom.xml 配置文件中添加依赖,如下:
-
-
<!--验证码-->
-
<dependency>
-
<groupId>com.github.whvcse</groupId>
-
<artifactId>easy-captcha</artifactId>
-
<version>1.6.2</version>
-
</dependency>
-
把生成的验证码结果保存到 redis 缓存中,并设置过期时间。
-
前端通过提交验证码和 key,其中 key 就是保存到 redis 中的键,通过这个键获取到对应的值,再与前端提交的值对比,相同就通过验证。
-
3|1 实现过程
-
新建验证码枚举类
-
由于 captcha 这款验证码提供了好几种验证码方法,有中文验证码,动态验证码,算术验证码等等,新建一个验证码每周类存放这几种验证码类型。代码如下:
-
-
// fhadmin.cn
-
public enum LoginCodeEnum {
-
/**
-
* 算数
-
*/
-
ARITHMETIC,
-
/**
-
* 中文
-
*/
-
CHINESE,
-
/**
-
* 中文闪图
-
*/
-
CHINESE_GIF,
-
/**
-
* 闪图
-
*/
-
GIF,
-
SPEC
-
}
-
该类是定义验证码的基本信息,例如高度、宽度、字体类型、验证码类型等等、并且我们把它转成通过 SpringBoot 配置文件类型来定义更加方便。
-
-
// fhadmin.cn
-
@Data
-
public class LoginCode {
-
-
/**
-
* 验证码配置
-
*/
-
private LoginCodeEnum codeType;
-
/**
-
* 验证码有效期 分钟
-
*/
-
private Long expiration = 2L;
-
/**
-
* 验证码内容长度
-
*/
-
private int length = 2;
-
/**
-
* 验证码宽度
-
*/
-
private int width = 111;
-
/**
-
* 验证码高度
-
*/
-
private int height = 36;
-
/**
-
* 验证码字体
-
*/
-
private String fontName;
-
/**
-
* 字体大小
-
*/
-
private int fontSize = 25;
-
-
/**
-
* 验证码前缀
-
* @return
-
*/
-
private String codeKey;
-
-
-
public LoginCodeEnum getCodeType() {
-
return codeType;
-
}
-
}
-
把配置文件转换 Pojo 类的统一配置类
-
-
// fhadmin.cn
-
@Configuration
-
public class ConfigBeanConfiguration {
-
-
@Bean
-
@ConfigurationProperties(prefix = "login")
-
public LoginProperties loginProperties() {
-
return new LoginProperties();
-
}
-
}
-
定义逻辑验证生成类
-
-
// fhadmin.cn
-
@Data
-
public class LoginProperties {
-
-
private LoginCode loginCode;
-
-
-
/**
-
* 获取验证码生产类
-
* @return
-
*/
-
public Captcha getCaptcha(){
-
if(Objects.isNull(loginCode)){
-
loginCode = new LoginCode();
-
if(Objects.isNull(loginCode.getCodeType())){
-
loginCode.setCodeType(LoginCodeEnum.ARITHMETIC);
-
}
-
-
}
-
return switchCaptcha(loginCode);
-
}
-
-
/**
-
* 依据配置信息生产验证码
-
* @param loginCode
-
* @return
-
*/
-
private Captcha switchCaptcha(LoginCode loginCode){
-
Captcha captcha = null;
-
synchronized (this){
-
switch (loginCode.getCodeType()){
-
case ARITHMETIC:
-
captcha = new FixedArithmeticCaptcha(loginCode.getWidth(),loginCode.getHeight());
-
captcha.setLen(loginCode.getLength());
-
break;
-
case CHINESE:
-
captcha = new ChineseCaptcha(loginCode.getWidth(),loginCode.getHeight());
-
captcha.setLen(loginCode.getLength());
-
break;
-
case CHINESE_GIF:
-
captcha = new ChineseGifCaptcha(loginCode.getWidth(),loginCode.getHeight());
-
captcha.setLen(loginCode.getLength());
-
break;
-
case GIF:
-
captcha = new GifCaptcha(loginCode.getWidth(),loginCode.getHeight());
-
captcha.setLen(loginCode.getLength());
-
break;
-
case SPEC:
-
captcha = new SpecCaptcha(loginCode.getWidth(),loginCode.getHeight());
-
captcha.setLen(loginCode.getLength());
-
default:
-
System.out.println("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
-
-
}
-
}
-
if(StringUtils.isNotBlank(loginCode.getFontName())){
-
captcha.setFont(new Font(loginCode.getFontName(),Font.PLAIN,loginCode.getFontSize()));
-
}
-
return captcha;
-
}
-
-
static class FixedArithmeticCaptcha extends ArithmeticCaptcha{
-
public FixedArithmeticCaptcha(int width,int height){
-
super(width,height);
-
}
-
-
@Override
-
protected char[] alphas() {
-
// 生成随机数字和运算符
-
int n1 = num(1, 10), n2 = num(1, 10);
-
int opt = num(3);
-
-
// 计算结果
-
int res = new int[]{n1 + n2, n1 - n2, n1 * n2}[opt];
-
// 转换为字符运算符
-
char optChar = "+-x".charAt(opt);
-
-
this.setArithmeticString(String.format("%s%c%s=?", n1, optChar, n2));
-
this.chars = String.valueOf(res);
-
-
return chars.toCharArray();
-
}
-
}
-
}
-
-
控制层定义验证生成接口
-
-
// fhadmin.cn
-
@ApiOperation(value = "获取验证码", notes = "获取验证码")
-
@GetMapping("/code")
-
public Object getCode(){
-
-
Captcha captcha = loginProperties.getCaptcha();
-
String uuid = "code-key-"+IdUtil.simpleUUID();
-
//当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型
-
String captchaValue = captcha.text();
-
if(captcha.getCharType()-1 == LoginCodeEnum.ARITHMETIC.ordinal() && captchaValue.contains(".")){
-
captchaValue = captchaValue.split("\\.")[0];
-
}
-
// 保存
-
redisUtils.set(uuid,captchaValue,loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);
-
// 验证码信息
-
Map<String,Object> imgResult = new HashMap<String,Object>(2){{
-
put("img",captcha.toBase64());
-
put("uuid",uuid);
-
}};
-
return imgResult;
-
-
}
-
前端调用接口
-
-
<template>
-
<div class="login-code">
-
<img :src="codeUrl" @click="getCode">
-
</div>
-
</template>
-
<script>
-
methods: {
-
getCode() {
-
getCodeImg().then(res => {
-
this.codeUrl = res.data.img
-
this.loginForm.uuid = res.data.uuid
-
})
-
},
-
}
-
created() {
-
// 获取验证码
-
this.getCode()
-
},
-
</script>
-
点击(此处)折叠或打开
-
-
-
1|0SpringBoot 版本
-
本文基于的 Spring Boot 的版本是 2.6.7 。
-
-
2|0 引入依赖
-
captcha 一款超简单的验证码生成,还挺好玩的。还有中文验证码,动态验证码. 。在项目中 pom.xml 配置文件中添加依赖,如下:
-
-
<!--验证码-->
-
<dependency>
-
<groupId>com.github.whvcse</groupId>
-
<artifactId>easy-captcha</artifactId>
-
<version>1.6.2</version>
-
</dependency>
-
把生成的验证码结果保存到 redis 缓存中,并设置过期时间。
-
前端通过提交验证码和 key,其中 key 就是保存到 redis 中的键,通过这个键获取到对应的值,再与前端提交的值对比,相同就通过验证。
-
3|1 实现过程
-
新建验证码枚举类
-
由于 captcha 这款验证码提供了好几种验证码方法,有中文验证码,动态验证码,算术验证码等等,新建一个验证码每周类存放这几种验证码类型。代码如下:
-
-
// fhadmin.cn
-
public enum LoginCodeEnum {
-
/**
-
* 算数
-
*/
-
ARITHMETIC,
-
/**
-
* 中文
-
*/
-
CHINESE,
-
/**
-
* 中文闪图
-
*/
-
CHINESE_GIF,
-
/**
-
* 闪图
-
*/
-
GIF,
-
SPEC
-
}
-
该类是定义验证码的基本信息,例如高度、宽度、字体类型、验证码类型等等、并且我们把它转成通过 SpringBoot 配置文件类型来定义更加方便。
-
-
// fhadmin.cn
-
@Data
-
public class LoginCode {
-
-
/**
-
* 验证码配置
-
*/
-
private LoginCodeEnum codeType;
-
/**
-
* 验证码有效期 分钟
-
*/
-
private Long expiration = 2L;
-
/**
-
* 验证码内容长度
-
*/
-
private int length = 2;
-
/**
-
* 验证码宽度
-
*/
-
private int width = 111;
-
/**
-
* 验证码高度
-
*/
-
private int height = 36;
-
/**
-
* 验证码字体
-
*/
-
private String fontName;
-
/**
-
* 字体大小
-
*/
-
private int fontSize = 25;
-
-
/**
-
* 验证码前缀
-
* @return
-
*/
-
private String codeKey;
-
-
-
public LoginCodeEnum getCodeType() {
-
return codeType;
-
}
-
}
-
把配置文件转换 Pojo 类的统一配置类
-
-
// fhadmin.cn
-
@Configuration
-
public class ConfigBeanConfiguration {
-
-
@Bean
-
@ConfigurationProperties(prefix = "login")
-
public LoginProperties loginProperties() {
-
return new LoginProperties();
-
}
-
}
-
定义逻辑验证生成类
-
-
// fhadmin.cn
-
@Data
-
public class LoginProperties {
-
-
private LoginCode loginCode;
-
-
-
/**
-
* 获取验证码生产类
-
* @return
-
*/
-
public Captcha getCaptcha(){
-
if(Objects.isNull(loginCode)){
-
loginCode = new LoginCode();
-
if(Objects.isNull(loginCode.getCodeType())){
-
loginCode.setCodeType(LoginCodeEnum.ARITHMETIC);
-
}
-
-
}
-
return switchCaptcha(loginCode);
-
}
-
-
/**
-
* 依据配置信息生产验证码
-
* @param loginCode
-
* @return
-
*/
-
private Captcha switchCaptcha(LoginCode loginCode){
-
Captcha captcha = null;
-
synchronized (this){
-
switch (loginCode.getCodeType()){
-
case ARITHMETIC:
-
captcha = new FixedArithmeticCaptcha(loginCode.getWidth(),loginCode.getHeight());
-
captcha.setLen(loginCode.getLength());
-
break;
-
case CHINESE:
-
captcha = new ChineseCaptcha(loginCode.getWidth(),loginCode.getHeight());
-
captcha.setLen(loginCode.getLength());
-
break;
-
case CHINESE_GIF:
-
captcha = new ChineseGifCaptcha(loginCode.getWidth(),loginCode.getHeight());
-
captcha.setLen(loginCode.getLength());
-
break;
-
case GIF:
-
captcha = new GifCaptcha(loginCode.getWidth(),loginCode.getHeight());
-
captcha.setLen(loginCode.getLength());
-
break;
-
case SPEC:
-
captcha = new SpecCaptcha(loginCode.getWidth(),loginCode.getHeight());
-
captcha.setLen(loginCode.getLength());
-
default:
-
System.out.println("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
-
-
}
-
}
-
if(StringUtils.isNotBlank(loginCode.getFontName())){
-
captcha.setFont(new Font(loginCode.getFontName(),Font.PLAIN,loginCode.getFontSize()));
-
}
-
return captcha;
-
}
-
-
static class FixedArithmeticCaptcha extends ArithmeticCaptcha{
-
public FixedArithmeticCaptcha(int width,int height){
-
super(width,height);
-
}
-
-
@Override
-
protected char[] alphas() {
-
// 生成随机数字和运算符
-
int n1 = num(1, 10), n2 = num(1, 10);
-
int opt = num(3);
-
-
// 计算结果
-
int res = new int[]{n1 + n2, n1 - n2, n1 * n2}[opt];
-
// 转换为字符运算符
-
char optChar = "+-x".charAt(opt);
-
-
this.setArithmeticString(String.format("%s%c%s=?", n1, optChar, n2));
-
this.chars = String.valueOf(res);
-
-
return chars.toCharArray();
-
}
-
}
-
}
-
-
控制层定义验证生成接口
-
-
// fhadmin.cn
-
@ApiOperation(value = "获取验证码", notes = "获取验证码")
-
@GetMapping("/code")
-
public Object getCode(){
-
-
Captcha captcha = loginProperties.getCaptcha();
-
String uuid = "code-key-"+IdUtil.simpleUUID();
-
//当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型
-
String captchaValue = captcha.text();
-
if(captcha.getCharType()-1 == LoginCodeEnum.ARITHMETIC.ordinal() && captchaValue.contains(".")){
-
captchaValue = captchaValue.split("\\.")[0];
-
}
-
// 保存
-
redisUtils.set(uuid,captchaValue,loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);
-
// 验证码信息
-
Map<String,Object> imgResult = new HashMap<String,Object>(2){{
-
put("img",captcha.toBase64());
-
put("uuid",uuid);
-
}};
-
return imgResult;
-
-
}
-
前端调用接口
-
-
<template>
-
<div class="login-code">
-
<img :src="codeUrl" @click="getCode">
-
</div>
-
</template>
-
<script>
-
methods: {
-
getCode() {
-
getCodeImg().then(res => {
-
this.codeUrl = res.data.img
-
this.loginForm.uuid = res.data.uuid
-
})
-
},
-
}
-
created() {
-
// 获取验证码
-
this.getCode()
-
},
-
</script>
-