[Java应用] 图片验证码 Kaptcha

简单介绍

Kaptcha是一个简单的图片验证码生成工具,小巧,使用起来还是比较顺手的。

查了一下,官网项目很久没有更新了,估计现在也没有人维护了,因为是google的域名,所以想看的话还得自己去翻墙。

工作原理

图片验证码的工作原理都是一样的,服务端生成随机字符串,以图片的形式给到客户端,客户端用户输入图片上的验证码,服务端验证用户输入的验证码是否正确。

验证码存在的意义是为了系统安全,确保客户端用户是个活生生的人,而不是机器程序在搞恶意攻击。

项目实践

搭建一个spring boot项目,用vue做一个简单的图片验证码页面,最后给出项目源码,仅供参考。

第一步:创建一个spring boot web项目,可正常启动,接收请求并响应。

第二步:引入Kaptcha依赖jar包,就一个,也是最新版本。

<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>

第三步:根据需求对Kaptcha进行相关配置。

/**
 * Kaptcha 详细属性配置项可查看 {@link com.google.code.kaptcha.Constants} 类
 *
 * @return
 */
@Bean
public DefaultKaptcha getDefaultKaptcha() {
    DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
    Properties properties = new Properties();
    properties.setProperty(Constants.KAPTCHA_BORDER, "yes");// 图片边框
    properties.setProperty(Constants.KAPTCHA_BORDER_COLOR, "105,179,90");// 边框颜色
    properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");// 字体颜色
    properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "10");
    properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "160");// 图片宽
    properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "50");// 图片高
    properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "30");// 字体大小
    properties.setProperty(Constants.KAPTCHA_SESSION_CONFIG_KEY, "verificationCode");// session key
    properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");// 验证码长度
    properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, "宋体,楷体,微软雅黑");// 字体
    Config config = new Config(properties);
    defaultKaptcha.setConfig(config);
    return defaultKaptcha;
}

这是spring boot的代码配置方法,如果是传统的spring项目,需要使用xml配置,配置参数都是一样的,形式不一样。

全面详细的配置项可以参考下表:

Constant描述默认值
kaptcha.border图片边框,合法值:yes , noyes
kaptcha.border.color边框颜色,合法值:r,g,b (and optional alpha) 或者 white,black,blueblack
kaptcha.border.thickness边框厚度,合法值:> 01
kaptcha.image.width图片宽度200
kaptcha.image.height图片高度50
kaptcha.producer.impl图片实现类com.google.code.kaptcha.impl.DefaultKaptcha
kaptcha.textproducer.impl文本实现类com.google.code.kaptcha.text.impl.DefaultTextCreator
kaptcha.textproducer.char.string文本集合,验证码值从此集合中获取abcde2345678gfynmnpwx
kaptcha.textproducer.char.length验证码长度5
kaptcha.textproducer.font.names字体Arial, Courier
kaptcha.textproducer.font.size字体大小40px
kaptcha.textproducer.font.color字体颜色,合法值: r,g,b 或者 white,black,blueblack
kaptcha.textproducer.char.space文字间隔2
kaptcha.noise.impl干扰实现类com.google.code.kaptcha.impl.DefaultNoise
kaptcha.noise.color干扰 颜色,合法值: r,g,b 或者 white,black,blueblack
kaptcha.obscurificator.impl

图片样式:

水纹 com.google.code.kaptcha.impl.WaterRipple

鱼眼 com.google.code.kaptcha.impl.FishEyeGimpy

阴影 com.google.code.kaptcha.impl.ShadowGimpy

com.google.code.kaptcha.impl.WaterRipple
kaptcha.background.impl背景实现类com.google.code.kaptcha.impl.DefaultBackground
kaptcha.background.clear.from背景颜色渐变,开始颜色light grey
kaptcha.background.clear.to背景颜色渐变, 结束颜色white
kaptcha.word.impl文字渲染器com.google.code.kaptcha.text.impl.DefaultWordRenderer
kaptcha.session.keyKaptcha提供的常量值,可做服务端存储的key值KAPTCHA_SESSION_KEY
kaptcha.session.dateKaptcha提供的常量值,可做服务端存储的key值KAPTCHA_SESSION_DATE

第四步:配置好Kaptcha属性以后,在需要的地方注入defaultKaptcha对象。

private DefaultKaptcha defaultKaptcha;

@Autowired
public void setDefaultKaptcha(DefaultKaptcha defaultKaptcha) {
    this.defaultKaptcha = defaultKaptcha;
}

这里没有使用字段注入(Field injection)方式,因为最近升级了IDE,发现使用字段注入的时候,IDE会提醒:Field injection is not recommended。查了一下,发现我们在Spring项目里使用最多的注入方式竟然是Spring最不推荐的方式!所以,以后还是改用另外两种方式吧:构造器注入,setter注入。

第五步:提供生成图片验证码的接口,验证码在服务端存储一份,同时转换成图片形式,返回给客户端。

随机字符串的生成可以使用Kaptcha提供的方法,也可以自己定义,反正就是个随机字符串而已。

@GetMapping("/verificationCode")
public void verificationCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
    try {
        // 生成验证码并保存在session中
        String text = defaultKaptcha.createText();
        // Constants.KAPTCHA_SESSION_KEY 是 kaptcha 提供好的 session key,可以直接拿来用,通常不需要自己再定义
        request.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY, text);
        // 生成验证码图片
        BufferedImage image = defaultKaptcha.createImage(text);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", baos);
        // 响应给客户端
        ServletOutputStream responseOutputStream = response.getOutputStream();
        responseOutputStream.write(baos.toByteArray());
        responseOutputStream.flush();
        responseOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
    }
}

第六步:提供接口,校验客户端输入验证码的正确性。

需要注意的是,一个验证码应该只能使用一次,不论验证通过与否,都应该删除服务端储存的验证码,让客户端重新获取并进行验证,防止客户端用户或者机器程序不断试错。

@PostMapping("/login")
public String login(HttpServletRequest request, String verificationCode) {
    HttpSession session = request.getSession();
    String sessionCode = (String) session.getAttribute(Constants.KAPTCHA_SESSION_KEY);
    if (sessionCode == null || sessionCode.isEmpty()) return "failed";
    if (!sessionCode.equals(verificationCode)) {// 验证失败
        session.removeAttribute(Constants.KAPTCHA_SESSION_KEY);
        return "failed";
    } else {// 验证成功
        session.removeAttribute(Constants.KAPTCHA_SESSION_KEY);
        return "success";
    }
}

第七步:编写客户端页面逻辑,为用户提供验证功能。

<div id="app" class="container">
    <div class="row justify-content-md-center">
        <div class="col-6 border m-5 p-5">
            <div class="form-group">
                <img v-bind:src="imgSrc" v-on:click="changeCode" alt="验证码"/>
                <input v-model="verificationCode" class="form-control form-control-lg col-6 my-3" placeholder="输入验证码"/>
                <button v-on:click="submit" class="btn btn-success col-6">登录</button>
                <p class="h3 text-danger my-3">{{ message }}</p>
            </div>
        </div>
    </div>
</div>
<script>
    let app = new Vue({
        el: '#app',
        data: {
            imgSrc: '/verificationCode',
            verificationCode: '',
            message: ''
        },
        methods: {
            changeCode: function () {
                // 后面添加参数t起到清除缓存作用
                this.imgSrc = "/verificationCode?t=" + new Date() * 1;
            },
            submit: async function () {
                try {
                    if (this.verificationCode == '') {
                        this.message = "验证码不能为空";
                        return;
                    }
                    const response = await axios.post('/login?verificationCode=' + this.verificationCode);
                    let resp = response.data;
                    if (resp == 'success') {
                        this.message = "验证码输入正确";
                    } else {
                        this.message = "验证码输入不正确";
                        this.changeCode();
                    }
                } catch (error) {
                    console.error(error);
                }
            }
        }
    });
</script>

项目源码

项目地址:demo-kaptcha,运行方式:

// maven 启动
mvn spring-boot:run

// 访问地址
http://localhost:8080/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值