1、图形验证码设计
1.1思路
现今,市面上的图形验证码付费的,免费的多种多样,主要形式有滑动拼图、文字点选、语序点选、字体识别、空间推理、智能随机等。
而处理也分为web端和sever端两部分
此处以免费的kaptcha 为例,进行数字图形验证码的解析
2、server 端
2.1 controller
@RestController
@Slf4j
@RequestMapping("/sys")
public class SysLoginController {
@Resource
private ISysCaptchaService sysCaptchaService;
@GetMapping("/captcha/{uuid}")
public void captcha(HttpServletResponse response, @PathVariable("uuid") String uuid) throws IOException {
response.setHeader("Cache-Control", "no-store, no-cache");
response.setContentType("image/jpeg");
//获取图片验证码
BufferedImage image = sysCaptchaService.getCaptcha(uuid);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(image, "jpg", out);
IOUtils.closeQuietly(out);
}
}
2.2 service
public interface ISysCaptchaService extends IService<SysCaptcha> {
/**
* 获取图片验证码
*
* @param uuid uuid
* @return Image
*/
BufferedImage getCaptcha(String uuid);
}
2.3 serviceImpl
//此处引入了kaptcha的Producer
import com.google.code.kaptcha.Producer;
@Service
public class SysCaptchaServiceImpl extends ServiceImpl<SysCaptchaMapper, SysCaptcha> implements ISysCaptchaService {
@Resource
private Producer producer;
@Override
public BufferedImage getCaptcha(String uuid) {
if (StrUtil.isBlank(uuid)) {
throw new RuntimeException("uuid不能为空");
}
//生成文字验证码
String code = producer.createText();
SysCaptcha captchaEntity = new SysCaptcha();
captchaEntity.setUuid(uuid);
captchaEntity.setCode(code);
//5分钟后过期
captchaEntity.setExpireTime(DateUtil.offset(DateUtil.date(), DateField.MINUTE, 5).toLocalDateTime());
//将数据写入数据库,此处最好可以写入到redis等缓存中,不需要过期手动处理
this.save(captchaEntity);
return producer.createImage(code);
}
}
2.4 配置KaptchaConfig
@Configuration
public class KaptchaConfig {
@Bean
public DefaultKaptcha producer() {
Properties properties = new Properties();
properties.put("kaptcha.border", "no");
properties.put("kaptcha.textproducer.font.color", "black");
properties.put("kaptcha.textproducer.char.space", "5");
properties.put("kaptcha.textproducer.font.names", "Arial,Courier,cmr10,宋体,楷体,微软雅黑");
Config config = new Config(properties);
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
不进行config配置时,会报如下异常
**************************
APPLICATION FAILED TO START
***************************
Description:
A component required a bean of type 'com.google.code.kaptcha.Producer' that could not be found.
Action:
Consider defining a bean of type 'com.google.code.kaptcha.Producer' in your configuration.
2.5 pom.xml
<properties>
<kaptcha.version>2.3.5</kaptcha.version>
</properties>
<dependencies>
<dependency>
<groupId>com.youkol.support.kaptcha</groupId>
<artifactId>kaptcha-spring-boot-starter</artifactId>
<version>${kaptcha.version}</version>
</dependency>
</dependencies>
2.6 数据库表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for sys_captcha
-- ----------------------------
DROP TABLE IF EXISTS `sys_captcha`;
CREATE TABLE `sys_captcha` (
`uuid` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'uuid',
`code` varchar(6) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '验证码',
`expire_time` datetime NULL DEFAULT NULL COMMENT '过期时间',
PRIMARY KEY (`uuid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统验证码' ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
2.7 测试
3、web端
3.1 vue3 安装 uuid 小插件
3.1.1 安装
pnpm add vue3-uuid
如果pnpm安装异常
切换pnpm源
pnpm config set registry https://registry.npmmirror.com //切换淘宝源
3.1.2 main.ts中引入
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import pinia from '@/stores'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
//@ts-expect-error忽略当前文件ts类型的检测否则有红色提示(打包会失败)
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import 'virtual:svg-icons-register'
import '@/styles/index.scss'
//使用UUID
import UUID from 'vue3-uuid'
const app = createApp(App)
app.use(pinia)
app.use(router)
app.use(UUID)
app.use(ElementPlus, {
'locale': zhCn
})
app.mount('#app')
3.1.3 使用
import { uuid } from 'vue3-uuid'
const getCaptcha = () => {
const id = uuid.v4()
console.log('@@@@', id)
}
3.2 加载验证码
3.2.1 Template
<template>
<div class="container">
<el-row>
<el-col :span="12" :xs="0"></el-col>
<el-col :span="12" :xs="24">
<el-form
class="login_form"
:model="userStore.user"
:rules="loginRules"
ref="loginForm"
>
<h1>欢迎登录{{ setting.title }}</h1>
<el-form-item>
<el-input
v-model="userStore.user.username"
placeholder="请输入用户名"
prefix-icon="User"
></el-input>
</el-form-item>
<el-form-item>
<el-input
v-model="userStore.user.password"
placeholder="请输入密码"
prefix-icon="Lock"
show-password
></el-input>
</el-form-item>
<div class="captcha">
<el-form-item>
<el-input type="text" placeholder="请输入验证码"></el-input>
</el-form-item>
<el-form-item>
<el-image :src="captchaUrl" @click="getCaptcha" style="width: 150px;height: 30px"></el-image>
<el-button style="width: 150px;" @click="refresh">刷新</el-button>
</el-form-item>
</div>
<div class="class-btn">
<el-button type="primary" @click="login">登录</el-button>
<el-button type="primary" @click="register">注册</el-button>
</div>
</el-form>
</el-col>
</el-row>
</div>
</template>
3.2.2 script
<script setup lang="ts">
import { uuid } from 'vue3-uuid'
let captchaUrl = ref('')
const getCaptcha = async () => {
const id = uuid.v4()
console.log(id)
captchaUrl.value = import.meta.env.VITE_SERVER + '/sys/captcha/' + id
}
const refresh = () => {
getCaptcha()
}
onMounted(() => {
getCaptcha()
})
</script>