SpringBoot验证码的实现
这里前端使用到了Thymeleaf,所以要引入Thymeleaf的Maven
<!-- Thymeleaf --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
方式一:
相关Maven
<!-- 验证码依赖kaptcha --> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
配置注入
import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Properties; @Configuration public class KaptchaConfig { @Bean public DefaultKaptcha getDefaultKaptcha() { DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); Properties properties = new Properties(); // 图片边框 properties.setProperty("kaptcha.border", "yes"); // 边框颜色 properties.setProperty("kaptcha.border.color", "105,179,90"); // 字体颜色 properties.setProperty("kaptcha.textproducer.font.color", "red"); // 图片宽 properties.setProperty("kaptcha.image.width", "120"); // 图片高 properties.setProperty("kaptcha.image.height", "50"); // 字体大小 properties.setProperty("kaptcha.textproducer.font.size", "30"); // session key properties.setProperty("kaptcha.session.key", "code"); // 验证码长度 properties.setProperty("kaptcha.textproducer.char.length", "4"); // 字体 properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); Config config = new Config(properties); defaultKaptcha.setConfig(config); return defaultKaptcha; } }
controller层
@Slf4j @Controller public class LoginController { @Autowired private UserService userService; @Autowired private PasswordEncoder passwordEncoder; @Autowired private DefaultKaptcha captchaProducer; @RequestMapping("/{url}") public String redirect(@PathVariable String url){ return url; } //登录功能 @RequestMapping("/loginIn") public String login(@RequestParam("username") String username, @RequestParam("password") String password, String vrifyCode, Model model, HttpSession session){ log.info("登录用户:" + username); log.info("登录密码:" + password); if(username.equals("")){ model.addAttribute("key","用户名不能为空"); return "login"; }else if(password.equals("")) { model.addAttribute("key", "密码不能为空"); return "login"; }else if(!session.getAttribute("vrifyCode").equals(vrifyCode)){ //判断验证码是否一致 model.addAttribute("key","验证码不正确"); return "login"; }else { User user = userService.loginIn(username); if(user != null){ if(passwordEncoder.matches(password,user.getPassword())){ log.info(username + "用户登录成功"); //登录成功则存入用户信息到session中 session.setAttribute("LoginUser",username); return "index"; }else { log.info(username + "用户密码错误"); model.addAttribute("key","用户密码错误"); return "login"; } }else { log.info("登录失败," + username + "用户不存在"); model.addAttribute("key","登录失败," + username + "用户不存在"); return "login"; } } } //获取验证码的请求路径 @RequestMapping("/kaptcha") public void getKaptchaImage(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException { byte[] captchaChallengeAsJpeg = null; ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); try { //生产验证码字符串并保存到session中 String createText = captchaProducer.createText(); httpServletRequest.getSession().setAttribute("vrifyCode", createText); //使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中 BufferedImage challenge = captchaProducer.createImage(createText); ImageIO.write(challenge, "jpg", jpegOutputStream); } catch (IllegalArgumentException e) { httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND); return; } //定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组 captchaChallengeAsJpeg = jpegOutputStream.toByteArray(); httpServletResponse.setHeader("Cache-Control", "no-store"); httpServletResponse.setHeader("Pragma", "no-cache"); httpServletResponse.setDateHeader("Expires", 0); httpServletResponse.setContentType("image/jpeg"); ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream(); responseOutputStream.write(captchaChallengeAsJpeg); responseOutputStream.flush(); responseOutputStream.close(); } }
前端页面
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>登录页面</title> <link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}"/> <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script> <script> <!--验证码刷新--> function refresh() { $("#captcha_img").attr("src", ""); $("#captcha_img").attr("src", "/kaptcha"); } </script> </head> <body> <form role="form" th:action="@{/loginIn}" method="post"> <div style="color: red"> <input type="hidden" name="_method" th:text="${key}" th:if="${key!=null}"/> </div> <p> 账号:<input type="text" id="username" name="username"> <br> </p> <p> 密码:<input type="password" id="password" name="password"> <br> </p> <label>验证码:</label> <input type="text" name="vrifyCode"><br> <img th:src="@{/kaptcha}" onclick="refresh()" alt="无法显示图片" title="点击换图" id="captcha_img"><br><br> <p style="float:left;"> <input type="submit" id="login" value ="登录"> </p> </form> <form role="form1" th:action="@{/regist}" method="post"> <p style="float:left;"><input type="submit" id="regist" value="注册"></p> </form> </body> </html>
页面展示
方式二:
编写工具类
import java.awt.*; import java.awt.image.BufferedImage; import java.util.Random; public class VerifyUtil { /**验证码字符集*/ private static final char[] chars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; /**字符数量*/ private static final int SIZE = 4; /**干扰线数量*/ private static final int LINES = 5; /**宽度*/ private static final int WIDTH = 80; /**高度*/ private static final int HEIGHT = 40; /**字体大小*/ private static final int FONT_SIZE = 30; /** * 生成随机验证码及图片 * Object[0]:验证码字符串; * Object[1]:验证码图片。 */ public static Object[] createImage() { StringBuffer sb = new StringBuffer(); // 1.创建空白图片 BufferedImage image = new BufferedImage( WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); // 2.获取图片画笔 Graphics graphic = image.getGraphics(); // 3.设置画笔颜色 graphic.setColor(Color.LIGHT_GRAY); // 4.绘制矩形背景 graphic.fillRect(0, 0, WIDTH, HEIGHT); // 5.画随机字符 Random ran = new Random(); for (int i = 0; i <SIZE; i++) { // 取随机字符索引 int n = ran.nextInt(chars.length); // 设置随机颜色 graphic.setColor(getRandomColor()); // 设置字体大小 graphic.setFont(new Font( null, Font.BOLD + Font.ITALIC, FONT_SIZE)); // 画字符 graphic.drawString( chars[n] + "", i * WIDTH / SIZE, HEIGHT*2/3); // 记录字符 sb.append(chars[n]); } // 6.画干扰线 for (int i = 0; i < LINES; i++) { // 设置随机颜色 graphic.setColor(getRandomColor()); // 随机画线 graphic.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT), ran.nextInt(WIDTH), ran.nextInt(HEIGHT)); } // 7.返回验证码和图片 return new Object[]{sb.toString(), image}; } /** * 随机取色 */ public static Color getRandomColor() { Random ran = new Random(); Color color = new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256)); return color; } }
controller层
@Slf4j @Controller public class LoginController { @Autowired private UserService userService; @Autowired private PasswordEncoder passwordEncoder; @RequestMapping("/{url}") public String redirect(@PathVariable String url){ return url; }//登录功能 @RequestMapping("/loginIn") public String login(@RequestParam("username") String username, @RequestParam("password") String password, String vrifyCode, Model model, HttpSession session){ log.info("登录用户:" + username); log.info("登录密码:" + password); if(username.equals("")){ model.addAttribute("key","用户名不能为空"); return "login"; }else if(password.equals("")) { model.addAttribute("key", "密码不能为空"); return "login"; }else if(!session.getAttribute("vrifyCode").equals(vrifyCode)){ //判断验证码是否一致 model.addAttribute("key","验证码不正确"); return "login"; }else { User user = userService.loginIn(username); if(user != null){ if(passwordEncoder.matches(password,user.getPassword())){ log.info(username + "用户登录成功"); //登录成功则存入用户信息到session中 session.setAttribute("LoginUser",username); return "index"; }else { log.info(username + "用户密码错误"); model.addAttribute("key","用户密码错误"); return "login"; } }else { log.info("登录失败," + username + "用户不存在"); model.addAttribute("key","登录失败," + username + "用户不存在"); return "login"; } } } //获取验证码的请求路径 @RequestMapping("/getCode") public void getCode(HttpServletResponse response, HttpSession session) throws Exception { //利用图片工具生成图片 //第一个参数是生成的验证码,第二个参数是生成的图片 Object[] objs = VerifyUtil.createImage(); //将验证码存入Session session.setAttribute("vrifyCode", objs[0]); //将图片输出给浏览器 BufferedImage image = (BufferedImage) objs[1]; response.setContentType("image/png"); OutputStream os = response.getOutputStream(); ImageIO.write(image, "png", os); } }
前端页面
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>登录页面</title> <link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}"/> <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script> <script> <!--验证码刷新--> function refresh() { $("#captcha_img").attr("src", ""); $("#captcha_img").attr("src", "/getCode"); } </script> </head> <body> <form role="form" th:action="@{/loginIn}" method="post"> <div style="color: red"> <input type="hidden" name="_method" th:text="${key}" th:if="${key!=null}"/> </div> <p> 账号:<input type="text" id="username" name="username"> <br> </p> <p> 密码:<input type="password" id="password" name="password"> <br> </p> <label>验证码:</label> <input type="text" name="vrifyCode"><br><br> <img th:src="@{/getCode}" onclick="refresh()" alt="无法显示图片" title="点击换图" id="captcha_img"><br><br> <p style="float:left;"> <input type="submit" id="login" value ="登录"> </p> </form> <form role="form1" th:action="@{/regist}" method="post"> <p style="float:left;"><input type="submit" id="regist" value="注册"></p> </form> </body> </html>
页面展示