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日

相关文章

  • springboot 注册服务注册中心(zk)的两种方式详解

    Spring Boot 中注册服务到 Zookeeper 的两种方式详解 前言 服务注册和发现是分布式系统的关键问题之一,Spring Cloud 中采用 Eureka 作为服务注册和发现的组件,但是在 Zookeeper 这种经过时间验证并且稳定可靠的中间件也有许多人选择在使用中心化服务注册时采用它。Spring Boot 通过 spring-cloud-…

    Java 2023年5月19日
    00
  • Java 7大常见排序方法实例详解

    Java 7大常见排序方法实例详解 排序算法是计算机科学中的重要技能之一,Java为开发者提供了多种常见的排序方法,本文将介绍Java 7大常见排序方法并提供详细的示例说明。 1. 冒泡排序(Bubble Sort) 冒泡排序是最简单的排序算法之一,它的思想是依次比较相邻的两个元素,如果前面的元素比后面的元素大,则交换这两个元素的位置,通过多次比较和交换,将…

    Java 2023年5月26日
    00
  • 关于SpringMVC对Restful风格的支持详解

    关于SpringMVC对Restful风格的支持详解 在Web开发中,RESTful风格的API设计已经成为了一种趋势。SpringMVC作为一个流行的Web框架,也提供了对RESTful风格的支持。本文将详细讲解SpringMVC对RESTful风格的支持,包括如何使用@RequestMapping注解、如何使用@PathVariable注解、如何使用@R…

    Java 2023年5月18日
    00
  • 图文教程教你IDEA中的Spring环境搭建+简单入门

    图文教程:IDEA中的Spring环境搭建+简单入门 本文基于集成开发环境IntelliJ IDEA,为初学者讲解了如何搭建Spring环境和进行简单入门操作。下面是详细的步骤: 1. 安装IDEA 首先需要下载并安装IntelliJ IDEA,官方网站为:https://www.jetbrains.com/idea/download/。选择对应操作系统版本…

    Java 2023年5月19日
    00
  • 如何在Java中创建线程通信的四种方式你知道吗

    当多个线程共同操作同一个对象时,可能会遇到竞争态况或阻塞,需要使用线程通信来实现协调和同步,以确保程序的正确性和效率。在Java中,创建线程通信的方式有以下四种: 一、wait()和notify() wait()和notify()是Java中最基本的线程通信方式。wait()的作用是使当前线程挂起,直到另一个线程调用相同对象的notify()方法唤醒它。no…

    Java 2023年5月18日
    00
  • Midjourney 提示词工具(10 个国内外最好最推荐的)

    Midjourney,是一个革命性的基于人工智能的艺术生成器,可以从被称为提示的简单文本描述中生成令人惊叹的图像。Midjourney已经迅速成为艺术家、设计师和营销人员的首选工具(包括像我这样根本不会设计任何东西的无能之辈)。 为了帮助你开始使用这个强大的工具,我们汇编了一份15个资源的清单,可以帮助你为你的下一个项目制作更好的提示语……或者让我们…

    Java 2023年4月22日
    00
  • Maven工程打包jar的多种方式

    下面我来详细讲解一下 Maven 工程打包 jar 的多种方式。 Maven 是一个功能强大的构建工具,可以实现项目的自动化构建、测试和部署等,而制作 Jar 包作为项目的一部分就显得尤为重要了。在使用 Maven 打包 Jar 包时,有多种方式可以选择。 方式一:使用 Maven 插件打包 Maven 提供了一个非常便捷的打包方式,即使用 Maven 的插…

    Java 2023年5月19日
    00
  • jsp 网站引入外部css或者js失效问题解决

    当JSP网站引入外部CSS或JS时,如果失效,这可能是因为有一些问题。下面我将提供一些常见问题及其解决方案,以帮助您解决这些问题。 问题1:文件路径错误 引入外部CSS或JS时,需要确保文件路径正确。如果文件路径错误,浏览器将无法加载CSS或JS文件。解决此问题的方法是使用绝对路径或相对路径指定文件路径。 示例1:使用绝对路径指定文件路径 <link …

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