使用google的kaptcha包实现,可预定义验证码内容。
pom.xml:
<dependency> <groupId>com.google.code.kaptcha</groupId> <artifactId>kaptcha</artifactId> <version>2.3</version> <!--Kaptcha针对1.5和1.4提供了不同的分发包,这里使用classifier来区分--> <classifier>jdk15</classifier> </dependency>
CaptchaService:
package net.deniro.captcha; import java.util.List; /** * 验证码 * * @author deniro * 15-2-24上午10:49 */ public interface CaptchaService { /** * 生成随机验证码主键 * * @return * @throws CaptchaException */ String generateCaptchaKey() throws CaptchaException; /** * 生成验证码图片 * * @param captchaKey * @return * @throws CaptchaException */ byte[] generateCaptchaImage(String captchaKey) throws CaptchaException; /** * 验证用户返回的主键和值 * * @param captchaKey * @param captchaValue * @return * @throws CaptchaException */ boolean validateCaptcha(String captchaKey, String captchaValue) throws CaptchaException; /** * 获取 预定义验证码图片的内容 * * @return */ List<String> getPreDefinedTexts(); /** * 设置 预定义验证码图片的内容 * * 提高可测试性 * * @param preDefinedTexts */ void setPreDefinedTexts(List<String> preDefinedTexts); }
CaptchaServiceImpl:
package net.deniro.captcha; import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; import org.springframework.beans.factory.InitializingBean; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; /** * 验证码实现 * * @author deniro * 15-2-24上午11:05 */ public class CaptchaServiceImpl implements CaptchaService, InitializingBean { /** * 验证码生成器 */ private DefaultKaptcha producer; private Map<String, String> captchaMap = new HashMap<String, String>(); /** * 预定义验证码内容列表 */ private List<String> preDefinedTexts; /** * 预定义验证码内容列表索引 */ private int textCount = 0; /** * 生成随机验证码 * * @return * @throws CaptchaException */ @Override public String generateCaptchaKey() throws CaptchaException { String key = RandomGenerator.getRandomString();//主键的目的仅是标识验证码图片,本身没有实际意义 String value = getCaptchaText(); captchaMap.put(key, value); return key; } /** * 生成验证码字符串 * * @return */ private String getCaptchaText() { if (preDefinedTexts != null && !preDefinedTexts.isEmpty()) {//顺序循环字符串列表读取值 String text = preDefinedTexts.get(textCount); textCount = (textCount + 1) % preDefinedTexts.size(); return text; } else {//创建随机字符串 return producer.createText(); } } /** * 生成验证码图片 * * @param captchaKey * @return * @throws CaptchaException */ @Override public byte[] generateCaptchaImage(String captchaKey) throws CaptchaException { String text = captchaMap.get(captchaKey); if (text == null) { throw new CaptchaException("验证码' " + captchaKey + " ' 未找到。"); } BufferedImage image = producer.createImage(text); ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(image, "jpg", out); } catch (Exception e) { throw new CaptchaException("无法生成验证码流。"); } return out.toByteArray(); } /** * 验证 * * @param captchaKey * @param captchaValue * @return * @throws CaptchaException */ @Override public boolean validateCaptcha(String captchaKey, String captchaValue) throws CaptchaException { String text = captchaMap.get(captchaKey); if (text == null) { throw new CaptchaException("验证码主键' " + captchaKey + " '不存在!"); } if (text.equals(captchaValue)) { captchaMap.remove(captchaKey); return true; } else { return false; } } @Override public List<String> getPreDefinedTexts() { return preDefinedTexts; } @Override public void setPreDefinedTexts(List<String> preDefinedTexts) { this.preDefinedTexts = preDefinedTexts; } /** * 初始化验证码生成器,并提供默认配置 * <p/> * Spring初始化对象时调用 * * @throws Exception */ @Override public void afterPropertiesSet() throws Exception { producer = new DefaultKaptcha(); producer.setConfig(new Config(new Properties())); } }
RandomGenerator:
package net.deniro.captcha; import java.util.Random; /** * 随机码生成器 * * @author deniro * 15-2-24上午10:59 */ public class RandomGenerator { /** * 字符范围 */ private static String range="0123456789abcdefghijklmnopqrstuvwxyz"; /** * 获取随机字符串 * * 静态、线程安全 * @return */ public static synchronized String getRandomString(){ Random random=new Random(); StringBuilder result=new StringBuilder(); for (int i = 0; i < 8; i++) { result.append(range.charAt(random.nextInt(range.length()))); } return result.toString(); } }
CaptchaException:
package net.deniro.captcha; /** * 验证码异常 * * @author deniro * 15-2-24上午10:51 */ public class CaptchaException extends Exception { public CaptchaException(String message) { super(message); } public CaptchaException(String message, Throwable throwable) { super(message, throwable); } }
captcha.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="CaptchaService" class="net.deniro.captcha.CaptchaServiceImpl"></bean> </beans>
CaptchaServiceTest:
package captcha; import net.deniro.captcha.CaptchaService; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** * @author deniro * 15-2-24下午11:24 */ public class CaptchaServiceTest { private CaptchaService service; @Before public void prepare() throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("captcha.xml"); service = (CaptchaService) ctx.getBean("CaptchaService"); } @Test public void testGenerateCaptcha() throws Exception { List<String> preDefinedTexts = new ArrayList<String>(); preDefinedTexts.add("12345"); preDefinedTexts.add("abcde"); service.setPreDefinedTexts(preDefinedTexts); for (int i = 0; i < preDefinedTexts.size(); i++) { String captchaKey = service.generateCaptchaKey(); assertNotNull(captchaKey); byte[] captchaImage = service.generateCaptchaImage(captchaKey); assertTrue(captchaImage.length > 0); File image = new File("target/" + captchaKey + ".jpg"); OutputStream output = null; try { output = new FileOutputStream(image); output.write(captchaImage); } finally { if (output != null) { output.close(); } } assertTrue(image.exists() && image.length() > 0); } } @Test public void testValidateCaptchaCorrect() throws Exception { List<String> preDefinedTexts = new ArrayList<String>(); preDefinedTexts.add("12345"); preDefinedTexts.add("abcde"); service.setPreDefinedTexts(preDefinedTexts); String captchaKey = service.generateCaptchaKey(); service.generateCaptchaImage(captchaKey); assertTrue(service.validateCaptcha(captchaKey, "12345")); captchaKey = service.generateCaptchaKey(); service.generateCaptchaImage(captchaKey); assertTrue(service.validateCaptcha(captchaKey, "abcde")); } }
生成的验证码图片:
时间: 2024-10-10 08:37:08