您好,登录后才能下订单哦!
# SpringBoot配置Google Kaptcha验证码图片生成工具
## 一、验证码技术概述
验证码(CAPTCHA)是"Completely Automated Public Turing test to tell Computers and Humans Apart"的缩写,即全自动区分计算机和人类的图灵测试。在Web应用中,验证码主要用于:
1. 防止恶意注册和登录
2. 防止暴力破解
3. 防止自动化脚本攻击
4. 保护系统免受垃圾信息侵扰
Google Kaptcha是一个简单实用的验证码生成库,具有以下特点:
- 高度可配置的验证码样式
- 支持文本、数字和算术表达式
- 易于与Spring框架集成
- 良好的扩展性
## 二、环境准备
### 1. 创建SpringBoot项目
使用Spring Initializr创建项目,选择以下依赖:
- Spring Web
- Thymeleaf (可选,用于前端展示)
### 2. 添加Kaptcha依赖
在`pom.xml`中添加Kaptcha依赖:
```xml
<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>
创建配置类KaptchaConfig.java:
@Configuration
public class KaptchaConfig {
    
    @Bean
    public Producer kaptchaProducer() {
        Properties properties = new Properties();
        // 图片宽度
        properties.setProperty("kaptcha.image.width", "150");
        // 图片高度
        properties.setProperty("kaptcha.image.height", "50");
        // 文本集合,验证码值从此集合中获取
        properties.setProperty("kaptcha.textproducer.char.string", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        // 验证码长度
        properties.setProperty("kaptcha.textproducer.char.length", "4");
        // 字体
        properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
        // 字体颜色
        properties.setProperty("kaptcha.textproducer.font.color", "black");
        // 干扰线颜色
        properties.setProperty("kaptcha.noise.color", "gray");
        // 图片样式
        properties.setProperty("kaptcha.obscurificator.impl", 
            "com.google.code.kaptcha.impl.ShadowGimpy");
        
        Config config = new Config(properties);
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}
| 参数名称 | 默认值 | 说明 | 
|---|---|---|
| kaptcha.border | yes | 图片边框 | 
| kaptcha.border.color | black | 边框颜色 | 
| kaptcha.image.width | 200 | 图片宽度 | 
| kaptcha.image.height | 50 | 图片高度 | 
| kaptcha.textproducer.char.string | abcde2345678gfynmnpwx | 验证码字符集 | 
| kaptcha.textproducer.char.length | 5 | 验证码长度 | 
| kaptcha.textproducer.font.names | Arial | 字体 | 
| kaptcha.textproducer.font.size | 40px | 字体大小 | 
| kaptcha.textproducer.font.color | black | 字体颜色 | 
| kaptcha.noise.impl | com.google.code.kaptcha.impl.DefaultNoise | 干扰实现类 | 
| kaptcha.noise.color | black | 干扰颜色 | 
| kaptcha.background.clear.from | lightGray | 背景渐变起始色 | 
| kaptcha.background.clear.to | white | 背景渐变结束色 | 
@Controller
public class KaptchaController {
    
    @Autowired
    private Producer kaptchaProducer;
    
    @GetMapping("/captcha.jpg")
    public void getCaptcha(HttpServletResponse response, HttpSession session) throws IOException {
        // 设置响应头
        response.setContentType("image/jpeg");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        
        // 生成验证码文本
        String capText = kaptchaProducer.createText();
        // 将验证码存入session
        session.setAttribute("captcha", capText);
        
        // 生成验证码图片并写入响应
        try (OutputStream out = response.getOutputStream()) {
            BufferedImage bi = kaptchaProducer.createImage(capText);
            ImageIO.write(bi, "jpg", out);
            out.flush();
        }
    }
    
    @PostMapping("/verify")
    @ResponseBody
    public String verify(@RequestParam String code, HttpSession session) {
        String captcha = (String) session.getAttribute("captcha");
        if (code.equalsIgnoreCase(captcha)) {
            return "验证码正确";
        }
        return "验证码错误";
    }
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Kaptcha Demo</title>
</head>
<body>
    <form action="/verify" method="post">
        <img src="/captcha.jpg" onclick="this.src='/captcha.jpg?'+Math.random()" 
             style="cursor: pointer;" title="点击刷新验证码"/>
        <br/>
        <input type="text" name="code" placeholder="请输入验证码"/>
        <button type="submit">验证</button>
    </form>
</body>
</html>
实现com.google.code.kaptcha.GimpyEngine接口可以自定义验证码样式:
public class CustomGimpy implements GimpyEngine {
    @Override
    public BufferedImage getDistortedImage(BufferedImage baseImage) {
        // 自定义图片扭曲逻辑
        Graphics2D graph = baseImage.createGraphics();
        // 添加自定义效果...
        return baseImage;
    }
}
然后在配置中指定:
properties.setProperty("kaptcha.obscurificator.impl", "com.your.package.CustomGimpy");
@Bean
public Producer mathKaptcha() {
    Properties properties = new Properties();
    // 使用算术表达式
    properties.setProperty("kaptcha.textproducer.impl", 
        "com.google.code.kaptcha.text.impl.MathTextCreator");
    // 算式结果长度
    properties.setProperty("kaptcha.textproducer.char.length", "1");
    
    Config config = new Config(properties);
    DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
    defaultKaptcha.setConfig(config);
    return defaultKaptcha;
}
对于分布式系统,建议使用Redis存储验证码:
@Autowired
private RedisTemplate<String, String> redisTemplate;
@GetMapping("/captcha.jpg")
public void getCaptcha(HttpServletResponse response, 
                      @RequestParam String uuid) throws IOException {
    // ...生成验证码代码...
    
    // 存入Redis,设置5分钟过期
    redisTemplate.opsForValue().set("captcha:" + uuid, capText, 5, TimeUnit.MINUTES);
    
    // ...生成图片代码...
}
@PostMapping("/verify")
@ResponseBody
public String verify(@RequestParam String code, 
                    @RequestParam String uuid) {
    String captcha = redisTemplate.opsForValue().get("captcha:" + uuid);
    // ...验证逻辑...
}
使用Spring AOP或拦截器限制验证码获取频率:
@Aspect
@Component
public class RateLimitAspect {
    
    private final Map<String, Long> lastRequestTime = new ConcurrentHashMap<>();
    
    @Around("execution(* com..KaptchaController.getCaptcha(..)) && args(..,request)")
    public Object limit(ProceedingJoinPoint pjp, HttpServletRequest request) throws Throwable {
        String ip = request.getRemoteAddr();
        Long lastTime = lastRequestTime.get(ip);
        long current = System.currentTimeMillis();
        
        if (lastTime != null && current - lastTime < 60000) {
            throw new RuntimeException("请求过于频繁,请稍后再试");
        }
        
        lastRequestTime.put(ip, current);
        return pjp.proceed();
    }
}
可能原因: - 未正确配置Content-Type响应头 - 图片生成过程中出现异常 - 浏览器缓存问题
解决方案:
- 确保设置了response.setContentType("image/jpeg")
- 添加随机参数防止缓存:/captcha.jpg?t=123456
- 检查后台日志是否有异常
解决方案: - 增加干扰线和噪点 - 使用更复杂的字符集 - 实现动态字符间距和旋转 - 定期更换验证码样式
解决方案: - 使用Redis集中存储验证码 - 确保session共享配置正确 - 考虑使用JWT等无状态验证方式
本文详细介绍了如何在SpringBoot项目中集成Google Kaptcha验证码组件,包括:
通过合理配置和适当的安全措施,Kaptcha可以成为Web应用安全防护的有效工具。开发者应根据实际业务需求调整验证码的复杂度,在安全性和用户体验之间取得平衡。
提示:在实际项目中,建议将验证码与登录/注册流程的其他安全措施(如IP限制、密码强度检查等)结合使用,构建多层次的安全防护体系。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。