public abstract class AbstractCaptchaEngine extends ImageCaptchaEngine { private List<CaptchaFactory> factories = new ArrayList<CaptchaFactory>(); private Random myRandom = new SecureRandom(); public AbstractCaptchaEngine(String path) { buildInitialFactories(path); checkFactoriesSize(); } protected abstract void buildInitialFactories(String path); public boolean addFactory(ImageCaptchaFactory factory) { return this.factories.add(factory); } public void addFactories(ImageCaptchaFactory[] factories) { for (int i = 0; i < factories.length; i++) this.factories.add(factories[i]); } public CaptchaFactory[] getFactories() { return (CaptchaFactory[]) (CaptchaFactory[]) this.factories.toArray(new CaptchaFactory[this.factories.size()]); } public void setFactories(CaptchaFactory[] factories) throws CaptchaEngineException { if ((factories == null) || (factories.length == 0)) { throw new CaptchaEngineException("impossible to set null or empty factories"); } List<CaptchaFactory> tempFactories = new ArrayList<CaptchaFactory>(); for (int i = 0; i < factories.length; i++) { if (ImageCaptchaFactory.class.isAssignableFrom(factories[i].getClass())) { throw new CaptchaEngineException("This factory is not an image captcha factory " + factories[i].getClass()); } tempFactories.add(factories[i]); } this.factories = tempFactories; } public ImageCaptchaFactory getImageCaptchaFactory() { //nextInt(n)是从0到n的随机数(随机获取一个) return (ImageCaptchaFactory) this.factories.get(this.myRandom.nextInt(this.factories.size())); } @Override public ImageCaptcha getNextImageCaptcha() { return getImageCaptchaFactory().getImageCaptcha(); } @Override public ImageCaptcha getNextImageCaptcha(Locale locale) { //Local那个 return getImageCaptchaFactory().getImageCaptcha(locale); } private void checkFactoriesSize() { if (this.factories.size() == 0) throw new CaptchaException("This gimpy has no factories. Please initialize it properly with the buildInitialFactory() called by the constructor or the addFactory() mehtod later!"); } }
/** * 仿照JCaptcha2.0编写GMail验证码样式的图片引擎. * * @author can */ public class GMailEngine extends AbstractCaptchaEngine { public static final String IMAGE_CAPTCHA_KEY = "imageCaptcha";// ImageCaptcha对象存放在Session中的key public static final String CAPTCHA_INPUT_NAME = "j_captcha";// 验证码输入表单名称 //public static final String CAPTCHA_IMAGE_URL = "/captcha";// 验证码图片URL private static final Integer MIN_WORD_LENGTH = 4;// 验证码最小长度 private static final Integer MAX_WORD_LENGTH = 4;// 验证码最大长度 private static final Integer IMAGE_HEIGHT = 26;// 验证码图片高度 private static final Integer IMAGE_WIDTH = 70;// 验证码图片宽度 private static final Integer MIN_FONT_SIZE = 15;// 验证码最小字体 private static final Integer MAX_FONT_SIZE = 15;// 验证码最大字体 private static final String RANDOM_WORD = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&";// 随机字符 //private static final String IMAGE_PATH = "com/rekoe/cms/captcha/";// 随机背景图片路径 // 验证码随机颜色 private static final Color[] RANDOM_COLOR = new Color[] { new Color(255, 255, 255), new Color(255, 220, 220), new Color(220, 255, 255), new Color(220, 220, 255), new Color(255, 255, 220), new Color(220, 255, 220) }; // 验证码随机字体 private static final Font[] RANDOM_FONT = new Font[] { new Font("nyala", Font.BOLD, MIN_FONT_SIZE), new Font("Arial", Font.BOLD, MIN_FONT_SIZE), new Font("Bell MT", Font.BOLD, MIN_FONT_SIZE), new Font("Credit valley", Font.BOLD, MIN_FONT_SIZE), new Font("Impact", Font.BOLD, MIN_FONT_SIZE) }; public GMailEngine(String path) { super(path); } /** * can *TODO:构建初始化工厂 * 2015年3月19日 */ @Override protected void buildInitialFactories(String path) { //验证码随机色 RandomListColorGenerator randomListColorGenerator = new RandomListColorGenerator(RANDOM_COLOR); //随机字符集 WordGenerator wordGenerator = new RandomWordGenerator(RANDOM_WORD); //干扰设置,new LineTextDecorator(new Integer(1),Color.WHITE) TextDecorator[] textDecorator = new TextDecorator[] {new BaffleTextDecorator( new Integer(1),randomListColorGenerator)}; //字体大小从(MIN_FONT_SIZE到MAX_FONT。随机字体 FontGenerator fontGenerator = new RandomFontGenerator(MIN_FONT_SIZE, MAX_FONT_SIZE, RANDOM_FONT); //背景 BackgroundGenerator backgroundGenerator = new FileReaderRandomBackgroundGenerator(IMAGE_WIDTH, IMAGE_HEIGHT, path); //字符长度变化从MIN_WORD_LENGTH到MAX_WORD_LENGTH,颜色随机集合, TextPaster textPaster = new DecoratedRandomTextPaster(MIN_WORD_LENGTH, MAX_WORD_LENGTH, randomListColorGenerator, textDecorator); // 生成 WordToImage wordToImage = new ComposedWordToImage ( fontGenerator, backgroundGenerator, textPaster ); //放入工厂 addFactory(new GimpyFactory(wordGenerator, wordToImage)); } }
public Object captcha(HttpServletRequest request) {//获取验证码,Object代表image // get the session id that will identify the generated captcha. //the same id must be used to validate the response, the session id is a good candidate // request.getLocale()本地化,确定是哪个工厂,不҉同҉国҉家҉使҉用҉字҉符҉不҉一҉样҉ String captchaId = request.getSession(true).getId(); return imageCaptchaService.getChallengeForID(captchaId, request.getLocale()); } //调用××××××××××××××××××××××××××根据浏览器输入的验证码,判断是否正确, boolean isRight = imageCaptchaService.validateResponseForID(sessionID,captchaString );
好吧,最后贡献下,JCaptcha源码(密҉码҉:24d6),按照源码采用策略模式的方式,完全可以订制自己专属的JCaptcha。
还有一点就是此框架为伤残人士提供语音(直接传҉递҉送҉门҉http://www.ibm.com/developerworks/cn/opensource/os-cn-jcaptcha/)(哈҉哈҉哈҉,你是的八分堡)