Java实现图片验证码具体代码

当网站需要进行用户登录、注册等操作时,为了防止机器人恶意攻击,通常会采用图片验证码的方式来验证用户是否为人类。下面介绍一种基于 Java 实现图片验证码的具体代码,包含验证码生成和校验流程。

生成验证码图片

验证码生成包含以下几个步骤:

  1. 生成随机字符串
/**
 * 生成指定长度的随机字符串
 * @param length 随机字符串长度
 * @return 随机字符串
 */
private static String generateRandomString(int length) {
    StringBuilder sb = new StringBuilder(length);
    for (int i = 0; i < length; i++) {
        int rand = (int) (Math.random() * CHARACTERS.length());
        sb.append(CHARACTERS.charAt(rand));
    }
    return sb.toString();
}

// 可用字符集
private static final String CHARACTERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  1. 创建图片
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
  1. 绘制字符串
g.setFont(new Font("Arial", Font.BOLD, FONT_SIZE));
for (int i = 0; i < randomString.length(); i++) {
    g.setColor(new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255)));
    g.drawString(String.valueOf(randomString.charAt(i)), i * FONT_SIZE + PADDING_LEFT, FONT_BASELINE_Y);
}
  1. 绘制干扰线和干扰点
for (int i = 0; i < LINE_NUM; i++) {
    g.setColor(new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255)));
    int x1 = (int) (Math.random() * WIDTH);
    int y1 = (int) (Math.random() * HEIGHT);
    int x2 = (int) (Math.random() * WIDTH);
    int y2 = (int) (Math.random() * HEIGHT);
    g.drawLine(x1, y1, x2, y2);
}

for (int i = 0; i < DOT_NUM; i++) {
    g.setColor(new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255)));
    int x = (int) (Math.random() * WIDTH);
    int y = (int) (Math.random() * HEIGHT);
    g.fillOval(x, y, 1, 1);
}
  1. 将图片转为 byte 数组
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(image, "JPEG", bos);
byte[] imageBytes = bos.toByteArray();
  1. 将随机字符串和图片 byte 数组存入 Redis(可选)

存入 Redis 的目的是方便用户后续的验证码校验,可以将随机字符串作为 key,图片 byte 数组作为 value,设置过期时间,保证验证码的时效性。存入 Redis 示例代码:

String key = "captcha:" + randomString;
redisTemplate.opsForValue().set(key, imageBytes, CAPTCHA_EXPIRE_MILLISECONDS, TimeUnit.MILLISECONDS);

校验验证码

验证码校验包含以下几个步骤:

  1. 获取随机字符串

随机字符串可以从用户提交的表单中获取。

  1. 获取 Redis 中的图片 byte 数组

从 Redis 中获取随机字符串对应的图片 byte 数组,如果获取失败,说明验证码已失效,需要重新生成验证码。

String key = "captcha:" + randomString;
byte[] imageBytes = redisTemplate.opsForValue().get(key);
if (imageBytes == null || imageBytes.length == 0) {
    // 验证码已失效,需要重新生成验证码
    return false;
}
  1. 校验用户提交的验证码和图片中的验证码是否匹配
String userCaptcha = ...; // 用户提交的验证码
String realCaptcha = RecognizeImage.recognize(imageBytes); // 调用图片识别工具获取图片中的验证码
return userCaptcha.equalsIgnoreCase(realCaptcha);

其中,RecognizeImage 是一个图片识别工具类,可以使用 tesseract-ocrjava-ocr 等开源工具实现验证码识别,这里不再赘述。

示例1:Spring Boot 集成 Redis 实现验证码生成和校验

@RestController
@RequestMapping("/captcha")
public class CaptchaController {
    @Resource
    private StringRedisTemplate redisTemplate;

    @GetMapping("/image")
    public ResponseEntity<byte[]> getImageCaptcha(HttpSession session) throws IOException {
        String captcha = generateRandomString(CAPTCHA_LENGTH);
        byte[] imageBytes = generateImageCaptcha(captcha);
        String key = "captcha:image:" + captcha;
        redisTemplate.opsForValue().set(key, captcha, CAPTCHA_EXPIRE_SECONDS, TimeUnit.SECONDS);
        return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(imageBytes);
    }

    @PostMapping("/verify")
    public boolean verifyCaptcha(@RequestParam String captcha, HttpSession session) {
        String key = "captcha:image:" + captcha;
        String realCaptcha = redisTemplate.opsForValue().get(key);
        if (realCaptcha == null) {
            // 验证码已失效
            return false;
        } else {
            // 验证码校验
            redisTemplate.delete(key); // 删除验证码
            return captcha.equalsIgnoreCase(realCaptcha);
        }
    }
}

示例2:使用 Jedis 实现验证码的存取

public class CaptchaUtil {
    private static final String REDIS_HOST = "localhost";
    private static final int REDIS_PORT = 6379;
    private static final JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), REDIS_HOST, REDIS_PORT);

    // 生成图片验证码并存入 Redis
    public static String generateAndSaveImageCaptcha(int length, int width, int height) throws IOException {
        String captcha = generateRandomString(length);
        byte[] imageBytes = generateImageCaptcha(captcha, width, height);
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.setex(captcha, CAPTCHA_EXPIRE_SECONDS, new String(imageBytes));
        }
        return captcha;
    }

    // 从 Redis 中获取并校验验证码
    public static boolean verifyImageCaptcha(String captcha, String userInput) {
        try (Jedis jedis = jedisPool.getResource()) {
            String realCaptcha = jedis.get(captcha);
            if (realCaptcha == null) {
                // 验证码已失效
                return false;
            } else {
                // 验证码校验
                jedis.del(captcha); // 删除验证码
                String imageString = realCaptcha.substring(1, realCaptcha.length() - 1).replace("\\", "");
                String realUserInput = RecognizeImage.recognize(Base64.getDecoder().decode(imageString));
                return userInput.equalsIgnoreCase(realUserInput);
            }
        }
    }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java实现图片验证码具体代码 - Python技术站

(0)
上一篇 2023年6月15日
下一篇 2023年6月15日

相关文章

  • Java 中实现随机无重复数字的方法

    实现随机无重复数字的方法,在 Java 中可以通过以下步骤来实现: 创建一个包含指定数字的列表。 使用 Collections 类的 shuffle() 方法来打乱数字的顺序。 从列表中取出前几个数字。 下面是一个示例代码,展示了如何实现随机无重复数字的方法: import java.util.ArrayList; import java.util.Coll…

    Java 2023年5月26日
    00
  • c#和java base64不一致的解决方法

    下面是关于“c#和java base64不一致的解决方法”的完整攻略,介绍如何解决c#和Java在base64编码上的差异问题。 问题背景 在编写应用程序时,我们经常需要将一些数据进行加密或者传输,在这个过程中,经常会用到base64编码。然而,尽管c#和Java都有对应的base64编解码方法,但是两种语言在实现上略有区别,这就导致了c#和Java在使用相…

    Java 2023年5月19日
    00
  • 使用Get方式提交数据到Tomcat服务器的方法

    下面是使用Get方式提交数据到Tomcat服务器的方法的完整攻略: 1. Get方式提交数据概述 在使用Get方式提交数据到Tomcat服务器之前,我们需要了解一下Get方式提交数据的基本概念,以及它和Post方式提交数据的区别。Get方式提交数据是指将数据塞入URL之中,浏览器将连接信息、参数信息和HTTP首部一起发送给服务器。相比较而言,Post方式提交…

    Java 2023年5月19日
    00
  • win7系统打开java的控制面板的方法

    要在Win7系统上打开Java控制面板,可按照以下步骤进行操作: 方法一:使用Windows搜索功能打开Java控制面板 点击Windows系统右下角的“开始”按钮; 在开始菜单中,点击“搜索程序和文件”栏目输入“Java”; 在搜索结果中,找到并点击“Java”选项; 在弹出的Java应用程序窗口中,点击“Java 控制面板”按钮。 示例一: 步骤1:在窗…

    Java 2023年5月26日
    00
  • 详解springSecurity之java配置篇

    关于“详解springSecurity之java配置篇”完整攻略,我们来详细说一下。 简介 SpringSecurity是基于Spring框架的安全框架,主要解决的是在应用程序中如何安全地进行身份认证和授权。本篇文档主要讲解如何使用Java配置的方式来进行SpringSecurity的配置。 步骤 1. 添加spring-security配置依赖 在 pom…

    Java 2023年5月20日
    00
  • SpringMVC实现RESTful风格:@PathVariable注解的使用方式

    简介 RESTful风格是一种Web服务的设计风格,它使用HTTP协议的GET、POST、PUT、DELETE等方法来实现对资源的操作。SpringMVC提供了一种简单的方式来实现RESTful风格,即使用@PathVariable注解。本文将介绍如何使用@PathVariable注解来实现RESTful风格,并提供两个示例说明。 示例1:获取用户信息 以下…

    Java 2023年5月17日
    00
  • Spring、SpringMVC和SpringBoot的区别及说明

    下面是关于“Spring、SpringMVC和SpringBoot的区别及说明”的完整攻略。 Spring、SpringMVC和SpringBoot的介绍 Spring Spring是一个企业级框架,主要用于开发Java应用程序。Spring框架提供了大量的功能,如依赖注入、面向切面编程、JDBC等等。Spring框架被设计为一个轻量级的框架,能够集成已有的…

    Java 2023年5月15日
    00
  • java使用jar包生成二维码的示例代码

    下面是Java使用jar包生成二维码的完整攻略: 1. 引入Jar包 在Java中使用二维码需要引入第三方Jar包,可以使用Zxing或者QrCode这两个常用的Jar包。这里以Zxing为例,可以从官网或者Maven库中下载获取。 2. 生成二维码 import java.awt.Color; import java.awt.Graphics2D; imp…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部