kaptcha 数字字母形式验证码
google kaptcha验证码生成器且可以配置生成的验证码格式
引入依赖:
<dependency> <groupId>com.github.axet</groupId> <artifactId>kaptcha</artifactId> <version>0.0.9</version> </dependency>
配置生成验证码格式
@Slf4j @Configuration public class KaptchaConfig { @Bean public DefaultKaptcha defaultKaptcha() { DefaultKaptcha kaptcha = new DefaultKaptcha(); Properties properties = new Properties(); //是否有边框 默认为true 我们可以自己设置yes,no properties.setProperty(Constants.KAPTCHA_BORDER, "no"); // 边框颜色 properties.setProperty(Constants.KAPTCHA_BORDER_COLOR, "220,220,220"); //验证码文本字符大小 properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "5"); // 验证码图片宽度 properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "147"); // 验证码图片高度 properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "34"); properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "25"); properties.setProperty(Constants.KAPTCHA_SESSION_KEY, "code"); properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier,cmr10,宋体,楷体,微软雅黑"); properties.setProperty(Constants.KAPTCHA_NOISE_COLOR, "164,128,55"); properties.setProperty(Constants.KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, "0123456789"); //config属性 Config config = new Config(properties); kaptcha.setConfig(config); return kaptcha; } }
测试:
@RestController @RequestMapping("/kaptcha") public class KaptChaController { @Autowired @Qualifier("defaultKaptcha") private DefaultKaptcha producer; @ApiOperation("图片验证码") @RequestMapping(value = "/captcha.jpg",method = RequestMethod.GET) public void captcha(HttpServletResponse response)throws IOException { response.setHeader("Cache-Control", "no-store, no-cache"); response.setContentType("image/jpeg"); //生成文字验证码 String text = producer.createText(); producer.createText(); //生成图片验证码 BufferedImage image = producer.createImage(text); ServletOutputStream out = response.getOutputStream(); ImageIO.write(image, "jpg", out); } }
表达式验证码
另外一种验证码生成格式是用户自定义配置生成的验证码,可以是表达式验证码
引入依赖:
<dependency> <groupId>com.baomidou</groupId> <artifactId>kaptcha-spring-boot-starter</artifactId> <version>1.1.0</version> </dependency>
接口:
@RequestMapping("/kcaptcha") public class KcaptchaController { @Autowired private Kaptcha kaptcha; @ApiOperation("登录 验证, 这里只需要判断验证码是否正确") @RequestMapping("/login") public Object login(String verifyCode, HttpServletRequest request) { try { final boolean result = kaptcha.validate(verifyCode, 60); if (result) { return "success"; } else { return null; } } catch (KaptchaIncorrectException e) { return null; } } @ApiOperation("用来产生验证码") @RequestMapping("/verifyCode") public void generateImage(HttpServletRequest request, HttpServletResponse response) throws IOException { final ImageUtil imageUtil = ImageUtil.getInstance(); //验证码图片 final ByteArrayInputStream image = imageUtil.getImage(); //验证码文字 final String verifyCode = imageUtil.getStr(); request.getSession().setAttribute("verifyCode",verifyCode); response.setContentType("image/jpeg"); byte[] bytes = new byte[1024]; try(final ServletOutputStream out = response.getOutputStream()){ while (image.read(bytes)!= -1 ){ out.write(bytes); } } } }
@Slf4j public class ImageUtil { /**验证码*/ private String str ; /**验证码图片*/ private ByteArrayInputStream image ; /**图片宽度*/ private int width = 350; /**图片高度*/ private int height = 46; private ImageUtil(){ init(); } public static ImageUtil getInstance(){ return new ImageUtil(); }; private void init(){ this.str= ""; final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); final Graphics g = image.getGraphics(); Random random = new Random(); g.setColor(getRandColor(200,250)); g.fillRect(0,0,width,height); g.setFont(new Font("Times New Roman", Font.PLAIN,20)); g.setColor(getRandColor(160,200)); for(int i = 0 ; i < 150 ; i ++){ int x = random.nextInt(width); int y = random.nextInt(height); int x1 = random.nextInt(50); int y1 = random.nextInt(50); g.drawLine(x,y,x+x1,y+y1); } // for(int i = 0 ; i < 6 ; i ++){ // final String rand = String.valueOf(random.nextInt(10)); // this.str += rand; // g.setColor(getRandColor(20,110)); // g.drawString(rand,(width / 6)*i,46); // } int num1 = random.nextInt(10); int num2 = random.nextInt(10); g.setColor(getRandColor(20,110)); g.drawString(String.valueOf(num1),(width/5)*0+6,36); g.drawString("+",(width/5)*1+6,36); g.drawString(String.valueOf(num2),(width/5)*2+6,36); g.drawString("=",(width/5)*3+6,36); g.drawString("?",(width/5)*4+6,36); this.str = String.valueOf(num1+num2); g.dispose(); ByteArrayInputStream inputStream = null; ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try{ final ImageOutputStream imageOut = ImageIO.createImageOutputStream(outputStream); ImageIO.write(image,"JPEG",imageOut); imageOut.close(); inputStream = new ByteArrayInputStream(outputStream.toByteArray()); }catch (Exception e){ System.out.println("验证码图片生成失败:"+e); } this.image = inputStream; } private Color getRandColor(int fc, int bc) { Random random = new Random(); if(fc > 255) { fc = 255;} if(bc > 255) { bc = 255;} int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r,g,b); } public String getStr() { return str; } public void setStr(String str) { this.str = str; } public ByteArrayInputStream getImage() { return image; } public void setImage(ByteArrayInputStream image) { this.image = image; } }
这种形式的验证码在验证的时候需要对生成的表达式验证码进行计算并结合用户输入的结果进行比对来校验结果
下面介绍几种表达式计算工具
javax script表达式计算
首先介绍下java自带的表达式计算工具包:javax.script
写一个demo 看下使用
public class JavaxscriptTest { private static char[] ops = new char[]{'+', '-', '*'}; private static String generateVerifyCode(Random rdm) { int num1 = rdm.nextInt(10); int num2 = rdm.nextInt(10); int num3 = rdm.nextInt(10); char op1 = ops[rdm.nextInt(3)]; char op2 = ops[rdm.nextInt(3)]; String exp = "" + num1 + op1 + num2 + op2 + num3; return exp; } private static Integer calc(String exp) { try { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); return (Integer) engine.eval(exp); } catch (Exception e) { e.printStackTrace(); return null; } } public static void main(String[] args) { String express = generateVerifyCode(new Random()); log.info("生成的表达式:{}", express); log.info("表达式计算结果:{}", calc(express)); } }
输出结果:
14:58:30.047 [main] INFO com.fariy.kaptcha.express.util.JavaxscriptTest - 生成的表达式:3+2-9
14:58:31.103 [main] INFO com.fariy.kaptcha.express.util.JavaxscriptTest - 表达式计算结果:-4
这种生成的表达式是随机生成的,主要方法是:
engine.eval(exp); 计算表达式结果
再来看另外一个表达式计算
common-jexl3
引入依赖
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-jexl3</artifactId> <version>3.1</version> </dependency>
如果结合 表达式模型来计算 再引入依赖
<dependency> <groupId>org.xidea</groupId> <artifactId>jsel</artifactId> <version>0.1.0</version> </dependency>
demo案例:
public static void test1() { JexlContext jexlContext = new MapContext(); jexlContext.set("var1", 1); jexlContext.set("var2", 2); JexlBuilder builder = new JexlBuilder(); JexlExpression expression = builder.create().createExpression("var1 + 2 * var2"); Object evaluate = expression.evaluate(jexlContext); log.info("evaluate :{} ", evaluate); } public static void test2() { Expression el = new ExpressionImpl("var1 + 2 * var2"); HashMap context = new HashMap(); context.put("var1", 111); context.put("var2", 2); Object evaluate = el.evaluate(context); log.info("evaluate :{} ", evaluate); log.info("var1 :{} ", context.get("var1")); log.info("var2 :{} ", context.get("var2")); context.put("var2", 3); log.info("var1 :{} ", context.get("var1")); log.info("var2 :{} ", context.get("var2")); log.info("evaluate2 :{} ", el.evaluate(context)); } public static void main(String[] args) { test2(); }
这一种表达式可以根据表达式计算模型传参进行计算,也可以对复杂嵌套结构进行计算
aviator计算
引入依赖
<dependency> <groupId>com.googlecode.aviator</groupId> <artifactId>aviator</artifactId> <version>5.3.0</version> </dependency>
demo:
public static void test1() { //数字型计算 log.info("数字计算:{}", AviatorEvaluator.execute("1.22+2.32+3")); //字符型计算 String exp1 = "'Hello '+ name"; Map<String, Object> env1 = new HashMap<>(); env1.put("name", "tony"); log.info("字符型计算:{}", AviatorEvaluator.execute(exp1, env1)); //判断型计算 String exp2 = "a+b>c"; Map<String, Object> env2 = new HashMap<>(); env2.put("a", 5); env2.put("b", 6); env2.put("c", 7); log.info("判断型计算:{}", AviatorEvaluator.execute(exp2, env2)); } public static void main(String[] args) { test1(); }
测试输出:
15:04:40.776 [main] INFO com.fariy.kaptcha.express.util.AviatorTest - 数字计算:6.54
15:04:40.783 [main] INFO com.fariy.kaptcha.express.util.AviatorTest - 字符型计算:Hello tony
15:04:40.784 [main] INFO com.fariy.kaptcha.express.util.AviatorTest - 判断型计算:true
Aviator支持三种类型计算:Boolean,字符串,和数字类型,可以发现Aviator 涵盖了表达式计算以及格式匹配替换,相对来说使用范围广泛