需求:验证码一码一用,验证之后,不管是成功还是失败,都需要重新获取或者刷新二维码。
大致思路:后端生成验证码后还需要生成一个UUID与之对应,存储到缓存(记得添加过期时间),把UUID和验证码反给前端,登录时后端使用前端传过来的UUID去缓存获取验证码,然后和前端传过来的验证码对比(一般忽略大小写)。
不重复造轮子,使用开源组件,两步完事:
第一步:添加依赖
<!-- 添加图形验证码依赖 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
<version>5.8.5</version>
</dependency>
第二步:接口编写
两个接口,两种方式:1.接口直接返回图片。2.接口返回base64字符串。
@Api(tags = "图形验证码-api")
@RequestMapping("/api/gv")
@RestController
public class CaptchaController {
// 模拟缓存
Map<String,String> cache = new HashMap<>();
/**
* 给前端返回一个验证码图片
* @return
*/
@ApiOperation("获取图形验证码")
@GetMapping("/identifyImage")
public void identifyImage(HttpServletResponse response,
@ApiParam(value = "图形验证码id,无值:生成验证码,有值:刷新验证码")
@RequestParam(name = "codeId", required = false) String codeId) throws IOException {
//定义图形验证码的长、宽、验证码字符数、干扰元素个数
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 90, 4, 100);
// 验证码值
String code = lineCaptcha.getCode();
System.out.println("验证码值:" + code);
// 模拟把验证码的值存储到缓存(记得添加过期时间)
if (codeId == null) {
System.out.println("获取图形码");
codeId = ToolUtil.simpleUUID();
// 保存图形码值
cache.put(codeId, code);
} else {
System.out.println("刷新图形码");
// 更新图形码值,此时此刻 图形码可能已经过期删除,那就相对于保存一个新的
cache.put(codeId, code);
}
// 图形验证码对应的UUID,id和验证码一一对应,用于刷新、验证
response.setHeader("codeId", codeId);
// 输出到客户端
try (ServletOutputStream outputStream = response.getOutputStream()) {
// 图形验证码写出,写出到流
lineCaptcha.write(outputStream);
} catch (Exception e) {
System.out.println("图形验证码输出错误");
}
}
/**
* 给前端返回一个base64格式的图片,前端需要转换为图片
* @return
*/
@ApiOperation("获取图形验证码base64")
@GetMapping("/identifyImageBase64")
public String identifyImageBase64() {
// 定义图形验证码的长和宽
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 90, 4, 100);
// 验证码值
String code = lineCaptcha.getCode();
System.out.println("验证码值:" + code);
// 验证码以base64的格式返回到客户端
return lineCaptcha.getImageBase64Data();
}
}
效果展示:
1. 接口直接返回图片。
2. 接口返回base64字符串。
前端处理后得到图片:
更多功能和用法可参考详细文档: Hutool参考文档