需求:验证码一码一用,验证之后,不管是成功还是失败,都需要重新获取或者刷新二维码。
大致思路:后端生成验证码后还需要生成一个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参考文档