自定义验证码 - kaptcha
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <version>2.6.0</version> </dependency> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
package org.example.captcha; import javax.servlet.http.HttpServletRequest; import java.awt.*; import java.awt.image.BufferedImage; import java.util.Random; /** * @author banjuan * @date 2021/11/30 2:48 下午 */ public class CodeUtil { /** * 将获取到的前端参数转为string类型 * @param request * @param key * @return */ public static String getString(HttpServletRequest request, String key) { try { String result = request.getParameter(key); if(result != null) { result = result.trim(); } if("".equals(result)) { result = null; } return result; }catch(Exception e) { return null; } } /** * 验证码校验 * @param request * @return */ public static boolean checkVerifyCode(HttpServletRequest request) { //获取生成的验证码 String verifyCodeExpected = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); //获取用户输入的验证码 String verifyCodeActual = CodeUtil.getString(request, "verifyCodeActual"); if (null != verifyCodeActual) { verifyCodeActual = verifyCodeActual.toLowerCase(); } if(verifyCodeActual == null ||!verifyCodeActual.equals(verifyCodeExpected)) { return false; } return true; } /** * 宽高可作为参数传入 */ private static final int WIDTH = 110; private static final int HEIGHT = 40; /** * 传入BufferedImage对象,并将生成好的验证码保存到BufferedImage中 * @param bufferedImage * @return */ public static String drawRandomText(BufferedImage bufferedImage) { Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics(); // 设置画笔颜色-验证码背景色 graphics.setColor(Color.WHITE); // 填充背景 graphics.fillRect(0, 0, WIDTH, HEIGHT); graphics.setFont(new Font("宋体,楷体,微软雅黑", Font.BOLD, 26)); // 数字和字母的组合 String baseNumLetter = "123456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"; StringBuilder builder = new StringBuilder(); // 旋转原点的 x 坐标 int x = 8; String ch; Random random = new Random(); for (int i = 0; i < 4; i++) { graphics.setColor(getRandomColor()); //设置字体旋转角度,角度小于30度 int degree = random.nextInt() % 30; int dot = random.nextInt(baseNumLetter.length()); ch = baseNumLetter.charAt(dot) + ""; builder.append(ch); //正向旋转 graphics.rotate(degree * Math.PI / 180, x, 24); graphics.drawString(ch, x, 24); //反向旋转 graphics.rotate(-degree * Math.PI / 180, x, 24); x += 24; } //画干扰线 for (int i = 0; i < 6; i++) { // 设置随机颜色 graphics.setColor(getRandomColor()); // 随机画线 graphics.drawLine(random.nextInt(WIDTH), random.nextInt(HEIGHT), random.nextInt(WIDTH), random.nextInt(HEIGHT)); } //添加噪点 for (int i = 0; i < 30; i++) { int x1 = random.nextInt(WIDTH); int y1 = random.nextInt(HEIGHT); graphics.setColor(getRandomColor()); graphics.fillRect(x1, y1, 2, 2); } return builder.toString(); } /** * 随机取色 */ private static Color getRandomColor() { Random ran = new Random(); return new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256)); } }
package org.example.captcha; import com.google.code.kaptcha.Constants; import com.google.code.kaptcha.Producer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.imageio.ImageIO; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.awt.image.BufferedImage; import java.io.IOException; /** * @author banjuan * @date 2021/11/30 2:45 下午 */ @Controller public class CodeController { @Autowired private Producer captchaProducer = null; @RequestMapping("/kaptcha") public void getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpSession session = request.getSession(); response.setDateHeader("Expires", 0); response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); response.addHeader("Cache-Control", "post-check=0, pre-check=0"); response.setHeader("Pragma", "no-cache"); response.setContentType("image/jpeg"); //生成验证码 String capText = captchaProducer.createText(); session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText); //向客户端写出 BufferedImage bi = captchaProducer.createImage(capText); ServletOutputStream out = response.getOutputStream(); ImageIO.write(bi, "jpg", out); try { out.flush(); } finally { out.close(); } } @RequestMapping("/verification") public void createImageCode(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession session = request.getSession(); //禁止缓存 response.setDateHeader("Expires", 0); response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); response.addHeader("Cache-Control", "post-check=0, pre-check=0"); response.setHeader("Pragma", "no-cache"); //设置响应格式为png图片 response.setContentType("image/png"); // 生成图片验证码 BufferedImage image = new BufferedImage(110, 40, BufferedImage.TYPE_INT_RGB); String randomText = CodeUtil.drawRandomText(image); session.setAttribute(Constants.KAPTCHA_SESSION_KEY, randomText.toLowerCase()); System.out.println("验证码->>>"+randomText); ServletOutputStream out = response.getOutputStream(); ImageIO.write(image, "png", out); out.flush(); out.close(); } @RequestMapping("/hellow") public String Hello() { return "hello"; } }
package org.example.captcha; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; /** * @author banjuan * @date 2021/11/30 2:59 下午 */ @RestController public class HelloWorld { @RequestMapping("/hello") public String hello(HttpServletRequest request) { if (!CodeUtil.checkVerifyCode(request)) { return "验证码有误!"; } else { return "hello,world"; } } }
package org.example.captcha; 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; /** * @author banjuan * @date 2021/11/30 3:01 下午 */ @Configuration public class KaptchaConfig { @Bean public DefaultKaptcha getDefaultKaptcha(){ // DefaultKaptcha captchaProducer = new DefaultKaptcha(); // Properties properties = new Properties(); // properties.setProperty("kaptcha.border", "no"); // //properties.setProperty("kaptcha.border.color", "105,179,90"); // properties.setProperty("kaptcha.textproducer.font.color", "black"); // properties.setProperty("kaptcha.image.width", "110"); // properties.setProperty("kaptcha.image.height", "40"); // properties.setProperty("kaptcha.textproducer.font.size", "24"); // properties.setProperty("kaptcha.session.key", "code"); // properties.setProperty("kaptcha.noise.color", "white"); // properties.setProperty("kaptcha.textproducer.char.space", "4"); // properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.FishEyeGimpy"); //// properties.setProperty("kaptcha.background.clear.from", "0,255,0"); //// properties.setProperty("kaptcha.background.clear.to", "255,255,0"); // properties.setProperty("kaptcha.textproducer.char.length", "4"); //// properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); // properties.setProperty("kaptcha.textproducer.font.names", "Algerian"); // Config config = new Config(properties); // captchaProducer.setConfig(config); // return captchaProducer; DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); Properties properties = new Properties(); // 图片边框 properties.setProperty("kaptcha.border", "no"); // 边框颜色 //properties.setProperty("kaptcha.border.color", "105,179,90"); // 字体颜色 properties.setProperty("kaptcha.textproducer.font.color", "red"); // 验证码整体宽度 properties.setProperty("kaptcha.image.width", "110"); // 验证码整体高度 properties.setProperty("kaptcha.image.height", "40"); // 文字个数 properties.setProperty("kaptcha.textproducer.char.length", "4"); // 文字大小 properties.setProperty("kaptcha.textproducer.font.size","24"); // 文字随机字体 properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); // 文字距离 properties.setProperty("kaptcha.textproducer.char.space","4"); // 干扰线颜色 properties.setProperty("kaptcha.noise.color","blue"); // 自定义验证码背景 //properties.setProperty("kaptcha.background.impl","com.dt.springbootdemo.config.kaptcha.NoKaptchaBackhround"); Config config=new Config(properties); defaultKaptcha.setConfig(config); return defaultKaptcha; } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript"> function refresh() { document.getElementById('captcha_img').src="/verification?"+Math.random(); } </script> </head> <body> <form action="/hello" method="post"> 验证码: <input type="text" placeholder="请输入验证码" name="verifyCodeActual"> <div class="item-input"> <img id="captcha_img" alt="点击更换" title="点击更换" onclick="refresh()" src="/verification" /> </div> <input type="submit" value="提交" /> </form> </body> </html>