学会这个工具的使用,让你快速生成验证码

简介: 前言验证码是我们做人机验证最常用的方式,常用于敏感操作的验证,比如:登录、注册、修改等。验证码的原理:不同的客户端拥有不同的 session 对象,在看到验证码图片的时刻,服务器后端代码生成图片并将随机字符存储到 session 中。

前言

验证码是我们做人机验证最常用的方式,常用于敏感操作的验证,比如:登录、注册、修改等。

验证码的原理:不同的客户端拥有不同的 session 对象,在看到验证码图片的时刻,服务器后端代码生成图片并将随机字符存储到 session 中。这样客户端看到的只能是图片,人工识别图片后将字符发送到服务器与 session 中的字符进行比对。

上面只是简单的介绍了验证码的原理,更多细节还需有 javaweb 相关基础知识,这篇文章适合有基础的同学。

最近几天我翻到了以前生成验证码的工具类,使用 Graphics2D 生成的图片,然后再以流的形式写出到客户端,这些代码还是有些问题的,都是硬编码。在以后的使用中我们可能有不同的需求都会导致代码重新修改,自定义一些样式都不是很方便。

所以我找到了 github 上的一个生成验证码的工具:kaptcha,下面我就给大家介绍一下 kaptcha 的使用。

kaptcha 的使用

我们就以一个 maven 构建的 web 项目为例

1、依赖 jar 包

在 pom.xml 文件中添加相关依赖

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

2、配置生成验证码的 servlet

修改 web.xml,添加 kaptcha 提供的 servlet 并配置映射路径

<servlet>
    <servlet-name>Kaptcha</servlet-name>
    <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>Kaptcha</servlet-name>
    <url-pattern>/captcha</url-pattern>
</servlet-mapping>

访问 http://localhost:8080/captcha 这时发现就已经可以产生验证码了,但还有个问题,验证码的随机字符存在哪里了?

3、探索 kaptcha

我们来查看 KaptchaServlet 这个类的源码,doGet 方法

@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
{
    // Set to expire far in the past.
    resp.setDateHeader("Expires", 0);
    // Set standard HTTP/1.1 no-cache headers.
    resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
    // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
    resp.addHeader("Cache-Control", "post-check=0, pre-check=0");
    // Set standard HTTP/1.0 no-cache header.
    resp.setHeader("Pragma", "no-cache");

    // return a jpeg
    resp.setContentType("image/jpeg");

    // create the text for the image
    String capText = this.kaptchaProducer.createText();

    // store the text in the session
    req.getSession().setAttribute(this.sessionKeyValue, capText);

    // store the date in the session so that it can be compared
    // against to make sure someone hasn't taken too long to enter
    // their kaptcha
    req.getSession().setAttribute(this.sessionKeyDateValue, new Date());

    // create the image with the text
    BufferedImage bi = this.kaptchaProducer.createImage(capText);

    ServletOutputStream out = resp.getOutputStream();

    // write the data out
    ImageIO.write(bi, "jpg", out);
}

有这样一段代码,获取字符后存入 session 中,键为 sessionKeyValue 这个变量的值

// create the text for the image
String capText = this.kaptchaProducer.createText();
// store the text in the session
req.getSession().setAttribute(this.sessionKeyValue, capText);

sessionKeyValue 这个变量的值在 init 方法中被赋值

this.sessionKeyValue = config.getSessionKey();

好我们进入 config.getSessionKey() 中查看代码,发现 session 的键为 Constants 这个类中的常量 Constants.KAPTCHA_SESSION_KEY

return this.properties.getProperty(Constants.KAPTCHA_SESSION_CONFIG_KEY, Constants.KAPTCHA_SESSION_KEY);

4、编写测试验证码是否正常使用的 servlet

我们来验证一下,编写一个 servlet

import com.google.code.kaptcha.Constants;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/test")
public class TestKaptchaServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        //获取传入的验证码
        String captcha = req.getParameter("captcha");
        if (null != captcha) {
            //获取实际session中的验证码
            String code = (String) req.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
            if (null == code){
                resp.sendRedirect("/captcha");
                return;
            }
            if (code.equalsIgnoreCase(captcha)) {
                out.print("验证输入正确");
            } else {
                out.print("验证码输入有误");
            }
        } else {
            out.print("必须输入验证码");
        }
        out.flush();
        out.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

先访问验证码 http://localhost:8080/captcha 然后访问 http://localhost:8080/test?captcha=验证码

以上这些默认配置能满足一般业务的使用了,下面通过深入解析 kaptcha 的源码自定义配置验证码的宽、高、边框、颜色、字符等

5、深入源码自定义配置 kaptcha

再来看一下 init 方法中的代码

@Override
public void init(ServletConfig conf) throws ServletException
{
    super.init(conf);

    // Switch off disk based caching.
    ImageIO.setUseCache(false);

    Enumeration<?> initParams = conf.getInitParameterNames();
    while (initParams.hasMoreElements())
    {
        String key = (String) initParams.nextElement();
        String value = conf.getInitParameter(key);
        this.props.put(key, value);
    }

    Config config = new Config(this.props);
    this.kaptchaProducer = config.getProducerImpl();
    this.sessionKeyValue = config.getSessionKey();
    this.sessionKeyDateValue = config.getSessionDate();
}

这段代码获取 servlet 的初始化参数,并将参数存入 config 对象中,看 config 中的一段代码

public boolean isBorderDrawn()
{
    String paramName = Constants.KAPTCHA_BORDER;
    String paramValue = this.properties.getProperty(paramName);
    return this.helper.getBoolean(paramName, paramValue, true);
}

没错,所有的参数名字都是 Constants 类中常量名称

public class Constants
{
    public final static String KAPTCHA_SESSION_KEY = "KAPTCHA_SESSION_KEY";

    public final static String KAPTCHA_SESSION_DATE = "KAPTCHA_SESSION_DATE";

    public final static String KAPTCHA_SESSION_CONFIG_KEY = "kaptcha.session.key";
    
    //省略其他代码
}

所以,可以给 KaptchaServlet 在 web.xml 配置参数,下面这些配置给大家参考

<servlet>
    <servlet-name>Kaptcha</servlet-name>
    <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>

    <!-- 是否有边框 -->
    <init-param>
        <param-name>kaptcha.border</param-name>
        <param-value>no</param-value>
    </init-param>
    <!-- 字体颜色 -->
    <init-param>
        <param-name>kaptcha.textproducer.font.color</param-name>
        <param-value>red</param-value>
    </init-param>
    <!-- 图片宽度 -->
    <init-param>
        <param-name>kaptcha.image.width</param-name>
        <param-value>135</param-value>
    </init-param>
    <!-- 使用哪些字符生成验证码 -->
    <init-param>
        <param-name>kaptcha.textproducer.char.string</param-name>
        <param-value>ACDEFHKPRSTWX345679</param-value>
    </init-param>
    <!-- 图片高度 -->
    <init-param>
        <param-name>kaptcha.image.height</param-name>
        <param-value>50</param-value>
    </init-param>
    <!-- 字体大小 -->
    <init-param>
        <param-name>kaptcha.textproducer.font.size</param-name>
        <param-value>38</param-value>
    </init-param>
    <!-- 干扰线的颜色 -->
    <init-param>
        <param-name>kaptcha.noise.color</param-name>
        <param-value>black</param-value>
    </init-param>
    <!-- 字符个数 -->
    <init-param>
        <param-name>kaptcha.textproducer.char.length</param-name>
        <param-value>6</param-value>
    </init-param>
    <!-- 使用哪些字体 -->
    <init-param>
        <param-name>kaptcha.textproducer.font.names</param-name>
        <param-value>Arial</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>Kaptcha</servlet-name>
    <url-pattern>/captcha</url-pattern>
</servlet-mapping>
相关文章
|
2月前
|
前端开发 NoSQL 安全
浅谈 前端验证码那些事
浅谈 前端验证码那些事
49 0
|
安全 机器人 Java
JavaSwing实现验证码功能
在Web应用程序开发中,验证码(CAPTCHA)是一种常见的安全措施,用于防止自动化机器人和恶意软件对网站进行攻击。本文将介绍如何使用JavaSwing来实现验证码功能,以帮助您加强Web应用程序的安全性。
123 0
|
安全 机器人 PHP
在线行为验证码推荐
想要保护您的网站免受恶意攻击?不妨考虑一款免费行为验证插件。该插件基于用户的行为模式进行验证,可有效区分真实用户和机器人。其中,滑动拼图是一种常见的在线行为验证方式,能够增加验证的难度,提高网站的安全性。通过使用这款免费插件,您可以为您的网站添加一道可靠的安全防线。
|
安全 前端开发 定位技术
推荐一个非常好的行为验证码项目!
KgCaptcha 结合了设备指纹、行为特征、访问频率、地理位置等多项技术,有效的拦截恶意登录、批量注册,阻断机器操作,拦截非正常用户。较传统验证码相比,用户无需再经过思考或输入操作,只需轻轻一滑即可进行验证。
推荐一个非常好的行为验证码项目!
|
文字识别 C++ Python
pycharml利用ddddocr和selenium识别验证码并登录
1OCR 2 ddddocr 3使用案例 4 常见问题 代码详情 获得XPATH方法
324 0
|
存储 XML JavaScript
手把手教你验证码检验的登录
在网站实际应用过程中,为了防止网站登录接口被机器人轻易地使用,产生一些没有意义的用户数据,所以,采用验证码进行一定程度上的拦截,当然,我们采用的还是一个数字与字母结合的图片验证码形式,后续会讲到更加复杂的数字计算类型的图片验证码,请持续关注我的博客。
818 0
|
Java Spring
网站验证码的设计与实现
网站验证码的设计与实现
|
JavaScript Java
实现登录时进行校验验证码的功能
JavaEE中,实现登录时进行校验验证码的功能(图文并茂!!!)
实现登录时进行校验验证码的功能
|
JavaScript 前端开发
简单的验证码功能
简单的验证码功能
简单的验证码功能
|
机器学习/深度学习 安全 Java
不得不说这个验证码生成库,牛逼了!
不得不说这个验证码生成库,牛逼了!
622 0
不得不说这个验证码生成库,牛逼了!