基于SpringBoot和Hutool工具包实现验证码的案例
作者:new Random()
验证码案例
随着安全性的要求越来越高,目前项目中很多都会使用验证码,只要涉及到登录,绝大多数都会有验证的要求,验证码的形式也是多种多样,更复杂的图形验证码和行为验证码已经成为了更流行的趋势。
验证码的实现方式很多,可以前端实现,也可以后端实现。网上也有比较多的插件或者工具包可以使用,这里选择使用 Hutool工具包 来实现一个简单的验证码案例。完整代码见文章末尾。
1. 需求
最终实现的验证码界面如下图所示:
1. 页面生成验证码
2. 输入验证码,点击提交,验证用户输入验证码是否正确且是否超时,正确且未超时则进行页面跳转,错误或已超时则进行提示,并更换验证码
2. 准备工作
创建SpringBoot项目,引入Spring-Web-MVC和Lombok的依赖包,前端界面会在后面提供.
3. 约定前后端交互接口
需求分析
后端需要提供两个服务:
- 生成验证码,并返回验证码.
- 校验验证码是否正确.
接口定义
1)生成验证码
请求:
请求URL:/captcha/get
响应:浏览器显示图片内容
浏览器给服务器发送一个 /captcha/get 请求,服务器返回一个图片,浏览器显示在页面上
2)校验验证码是否正确
请求:
请求URL:/captcha/check 请求参数:captcha=验证码字符串
响应:
true or false 根据用户输入的验证码,校验验证码是否正确,并判断验证码是否超时
4. Hutool 工具介绍
Hutool官网:https://hutool.cn/
Hutool参考文档:https://hutool.cn/docs/#/
要使用Hutool工具包,需要在pom.xml文件中添加对应的依赖,参考文档中有详细介绍:
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.16</version> </dependency>
在Hutolol参考文档中找到图形验证码部分:
接下来可以就可以参考Hutool工具提供的方法,快速生成验证码,里面的介绍非常清晰,很容易看懂。此处使用如下格式验证码:
5. 实现验证码
项目目录结构如下:
后端代码
实现接口
import cn.hutool.captcha.CaptchaUtil; import cn.hutool.captcha.LineCaptcha; import cn.hxxy.captchademo.config.CaptchaProperties; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.Date; @RestController @RequestMapping("/captcha") public class CaptchaController { @Autowired private CaptchaProperties captchaProp; @RequestMapping("/get") public void getCaptcha(HttpServletResponse response, HttpSession session) { //定义图形验证码的长和宽(配置默认值) LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(captchaProp.getWidth(), captchaProp.getHeight()); //细节问题,不影响程序 //设置返回类型 response.setContentType("image/jpeg"); //静止缓存 response.setHeader("Progma", "No-cache"); try { //图形验证码写出,可以写出到文件,也可以写出到流 lineCaptcha.write(response.getOutputStream()); //同时将验证码内容和当前时间戳存储到Session中 //此处Session的键可以配置成常量 session.setAttribute(captchaProp.getSession().getKey(), lineCaptcha.getCode()); session.setAttribute(captchaProp.getSession().getDate(), new Date()); //关流 response.getOutputStream().close(); } catch (IOException e) { throw new RuntimeException(e); } } //验证码生效时间限制 private static final long VALID_MILLIS_TIME = 60 * 1000; @RequestMapping("/check") public boolean checkCaptcha(String captcha, HttpSession session) { //保证传过来的参数是合法的 if (StringUtils.hasLength(captcha)) { //根据配置的默认session信息获取key和date String key = (String) session.getAttribute(captchaProp.getSession().getKey()); Date date = (Date) session.getAttribute(captchaProp.getSession().getDate()); //1.验证码正确(不区分大小写) 2.验证码还未失效 return key.equalsIgnoreCase(captcha) && System.currentTimeMillis() - date.getTime() < VALID_MILLIS_TIME; } return false; } }
代码解析:
通过@Autowired注解注入了一个CaptchaProperties对象,这个对象是用来配置图形验证码的属性的。使用这种方式是因为代码中的有些属性可能会在别处使用,且它们都是固定的,例如图形验证码的长和宽,Session的字段名等。将这些属性封装在一个对象中,并通过读取配置文件的方式绑定属性值。
在@RequestMapping注解的getCaptcha方法中,使用Hutool包的CaptchaUtil.createLineCaptcha方法创建了一个图形验证码对象lineCaptcha,其大小由配置文件中的captchaProp.getWidth()和captchaProp.getHeight()决定。然后,将验证码内容和当前时间戳存储到HttpSession中,以便后续校验验证码的时候使用。最后,将图形验证码写出到HttpServletResponse的输出流中,以返回给前端页面显示。
在@RequestMapping注解的checkCaptcha方法中,首先判断传入的验证码参数是否合法。如果合法,则从HttpSession中获取存储的验证码内容和时间戳信息,并进行比较。如果验证码正确且未过期,则返回true,否则返回false。
CaptchaProperties类的实现和配置文件(.yml)信息如下
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Data @Configuration @ConfigurationProperties(prefix = "captcha") public class CaptchaProperties { private Integer width; private Integer height; private Session session; //使用自定义的Session类 @Data public static class Session { private String key; private String date; } }
spring: application: name: captcha-demo captcha: width: 200 height: 100 session: key: CAPTCHA_SESSION_KEY date: CAPTCHA_SESSION_DATE
此处还没有前端代码,但是已经可以先测试了,通常写好一个接口就可以测试一下。
启动项目,再访问 http://127.0.0.1:8080/captcha/get 显示验证码图片如下:
通过 Fiddler 进行抓包,HTTP请求和响应数据如下,图片就在响应的body部分:
前端代码
注意前端代码要放在resources的static目录下
index.html(重点关注script标签内的代码):
<!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(); //使用attr()方法修改src属性值,获取一个新的验证码图片,后面添加一个时间戳参数来保证每次请求的验证码图片都是不同的 $(this).attr('src', '/captcha/get?dt=' + new Date().getTime()); }); //点击提交按钮,进行验证码校验 $("#checkCaptcha").click(function () { $.ajax({ url: "/captcha/check", type: "post", data: { captcha: $("#inputCaptcha").val() }, success: function (result) { if (result) { location.href = "success.html"; } else { alert("验证码错误或已超时"); //验证码错误,重新生成验证码 $("#verificationCodeImg").attr('src', '/captcha/get?dt=' + new Date().getTime()); $("#inputCaptcha").val(""); } } }); }); </script> </body> </html>
JavaScript代码中主要包含两部分逻辑:
点击图片,切换验证码: 当id为"verificationCodeImg"的图片被点击时,会触发click事件的回调函数。回调函数通过修改图片的src属性,向后端发送一个请求来获取新的验证码图片,并使用当前时间戳作为参数,以确保每次请求的验证码图片都是不同的。最后,将获取到的新图片显示出来。
点击提交按钮,进行验证码校验: 当id为"checkCaptcha"的按钮被点击时,会触发click事件的回调函数。回调函数通过使用jQuery的ajax方法发送一个POST请求到"/captcha/check"接口,并传递了一个名为"captcha"的参数,该参数的值为id为"inputCaptcha"的输入框中用户输入的验证码。
在请求成功后的回调函数中,会根据后端返回的结果(result)进行处理。如果校验成功,则跳转到"success.html"页面;如果校验失败,则弹出一个提示框显示"验证码错误或已超时",并重新生成新的验证码图片并清空输入框中的验证码。
success.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>验证成功页</title> </head> <body> <h1>验证成功</h1> </body> </html>
6. 运行测试
启动项目,浏览器访问 http://127.0.0.1:8080/index.html 或 http://localhost:8080/index.html
输入错误的验证码:
提示正确,且验证码能正确刷新,超时同样会提示以上错误。且点击验证码图片时,会重新生成验证码。
验证成功,页面正确跳转,测试完成。
以上就是基于SpringBoot和Hutool工具包实现验证码的案例的详细内容,更多关于SpringBoot Hutool验证码的资料请关注脚本之家其它相关文章!