前言
我们注意到我们登录网站的时候经常会用到网络验证码,今天我们就简单实现一个验证码的前后端交互问题,做一个小demo
准备
我们这里并不需要依靠原生的java来实现,而是只需要引入一个maven依赖,使用现成的封装好的即可,这是我使用的是hutool工具包
网址:Hutool🍬一个功能丰富且易用的Java工具库,涵盖了字符串、数字、集合、编码、日期、文件、IO、加密、数据库JDBC、JSON、HTTP客户端等功能。
参考文档:入门和安装 (hutool.cn)
注意:这里我们去maven仓库去寻找的时候,一定不要去找最新版本的
我们可以先去使用一下这里的验证码,先会用,不必先理解原理
当我么执行完这类代码就会发现,对应的文件夹出现了类似于这样的图片
后端
首先我们得先设计接口
我们这里第一个接口负责以流的方式写入数据给web客户端
第二个接口负责检查输入的验证码与实际的验证码是否一致
至于页面的跳转,我们交给前端即可
现在开始写接口
我们将需要设置的常量放在配置文件中,使用一个对象进行注入即可
spring: application: name: Captcha //验证码的长宽 captcha: width: 200 height: 100 //验证码设置的时间(为了设置过期时间) //key为了保存验证码的值 session: key: captcha_session_key date: captcha_session_date //个人喜好 server: port: 9090
这些常量都是无状态的,我们将其交给Spring管理
@Component @Data @ConfigurationProperties(prefix = "captcha") public class CaptchaProperties { private Integer width; private Integer height; private Session session; @Data public static class Session{ private String key; private String date; } }
我们将刚刚测试的代码改一改就可以将验证码图片写入web网站上
首先创建验证码对象,然后将验证码写入其输出流即可
然后为了多线程的问题,我们不可以将验证码属性提出成公共属性,以防被修改,我们可以使用session保存验证码和生成验证码的时间
获取验证码
@RequestMapping("/captcha") @RestController public class CaptchaController { //过期时间为一分钟 private final static long session_valid_timeout = 60 * 1000; //对象注入 @Autowired private CaptchaProperties captchaProperties; @RequestMapping("/get") public void getCaptcha(HttpSession session, HttpServletResponse response){ //获取验证码对象 LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(captchaProperties.getWidth(), captchaProperties.getHeight()); try { //写入输出流 lineCaptcha.write(response.getOutputStream()); //将验证码设置到session中,方便验证 session.setAttribute(captchaProperties.getSession().getKey(), lineCaptcha.getCode()); session.setAttribute(captchaProperties.getSession().getDate(), new Date()); } catch (IOException e) { throw new RuntimeException(e); } }
下面我们开始设计检查验证码的逻辑
注:后端代码最好是写一点检查一点,这样方便排除错误
检查验证码
首先需要一个输入的input获取输入框的数据,从而和session中的数据进行比较,注意先判空
@RequestMapping("/check") public Boolean check(String input,HttpSession session) { if(!StringUtils.hasLength(input)) { return false; } String savedCode = (String) session.getAttribute(captchaProperties.getSession().getKey()); Date savedDate = (Date) session.getAttribute(captchaProperties.getSession().getDate()); if(input.equalsIgnoreCase(savedCode)) { if(savedDate!=null && System.currentTimeMillis() - savedDate.getTime() < session_valid_timeout) { return true; }else{ return false; } } return false; } }
前端
前端书写大致了解会写就行
主要逻辑就是获取输入框中的文本交给后端的接口即可
注:这里的图片地址建议加上一个时间戳,防止浏览器缓存
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>验证码</title> <style> #inputCaptcha { height: 30px; vertical-align: middle; } #verificationCodeImg{ vertical-align: middle; } #checkCaptcha{ height: 40px; width: 100px; } </style> </head> <body> <h1>输入验证码</h1> <div id="confirm"> <input type="text" name="inputCaptcha" id="inputCaptcha"> <img id="verificationCodeImg" src="/captcha/get" style="cursor: pointer;" title="看不清?换一张" /> <input type="button" value="提交" id="checkCaptcha"> </div> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script> <script> $("#verificationCodeImg").click(function(){ $(this).hide().attr('src', '/captcha/get?dt=' + new Date().getTime()).fadeIn(); }); $("#checkCaptcha").click(function () { $.ajax({ url:"/captcha/check", type:"post", data:{ input:$("#inputCaptcha").val(), }, success:function(result){ if(result) { location.href="success.html" }else{ alert("验证码错误或超时") } } }); }); </script> </body> </html>
成果展示
成功则跳转,另一个网页随便写写就行
失败则提示