几种生成验证码的方式以及计算表达式的计算

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 涵盖了表达式计算以及格式匹配替换,相对来说使用范围广泛

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员路同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值