程序员人生 网站导航

JCaptcha算数式验证码

栏目:php教程时间:2015-08-13 08:30:38

前两天买了张火车票,使人egg碎的验证已无力吐槽,试了几次都让我开始怀疑我的IQ是否是合适再从事程序猿的这个”神圣的职业“了。今天分享的是1段比较传统而不失实用的验证,验证的意义想必大家都已知晓。

好了,语言总是苍白无力。直入真题来看代码的实现的吧。

操作环境:
jboss eap 6.2
tomcat也能够,比较懒直接用的jboss。大家有兴趣也能够试试,支持的服务更多,性能更加稳定些。
servlet
麻雀虽小,5脏俱全,做了小例子足以。
JCaptcha
jcaptcha是1个开源的验证码生成控件。1般用于生产图片类验证码,但也支持声音的验证。
JCaptcha的官方网站:http://jcaptcha.sourceforge.net/
另外还有对应的开源社区:http://www.oschina.net/p/jcaptcha/
这里使用的是 jcaptcha⑴.0-all.jar ,好像有点老,但是自己maven的nexus里面正好有。

主要分为几个步骤
1.BackgroundGenerator生成图片。包括图片的背风景,大小等样式。
2.生成文字、运算符。包括文字的格式,字体的种类,字体的最小最大样式。
3.利用JCaptcha的1个工具类WordToImage生成带文字的图片。
4.最后则是验证的进程

1、生成图片

package com.tgb.cfl; import com.octo.captcha.service.captchastore.FastHashMapCaptchaStore; import com.octo.captcha.service.image.DefaultManageableImageCaptchaService; import com.octo.captcha.service.image.ImageCaptchaService; public class BfferImageCss { private static DefaultManageableImageCaptchaService instance=null; public static int result; /** * 单例模式的类用于生成图片 * @return */ public static ImageCaptchaService getInstance() { VerifImage vi= new VerifImage(); result=vi.getResult(); if(instance==null){ instance = new DefaultManageableImageCaptchaService(new FastHashMapCaptchaStore(), vi, 180, 100000, 75000); }else{ instance.setCaptchaEngine(vi); } return instance; } }

2、设置图片样式、字体情势、操作符情势

package com.tgb.cfl; import java.awt.*; import java.util.Random; import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator; import com.octo.captcha.component.image.backgroundgenerator.FunkyBackgroundGenerator; import com.octo.captcha.component.image.color.ColorGenerator; import com.octo.captcha.component.image.color.RandomRangeColorGenerator; import com.octo.captcha.component.image.fontgenerator.FontGenerator; import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator; import com.octo.captcha.component.image.textpaster.TextPaster; import com.octo.captcha.component.image.textpaster.RandomTextPaster; import com.octo.captcha.component.image.wordtoimage.WordToImage; import com.octo.captcha.component.image.wordtoimage.ComposedWordToImage; import com.octo.captcha.component.word.wordgenerator.DummyWordGenerator; import com.octo.captcha.component.word.wordgenerator.WordGenerator; import com.octo.captcha.engine.image.ListImageCaptchaEngine; import com.octo.captcha.image.gimpy.GimpyFactory; public class VerifImage extends ListImageCaptchaEngine { static{ System.setProperty("java.awt.headless", "true"); } //壹 贰 叁 肆 伍 陆 柒 捌 玖 private final static String[] nods={"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"}; //1,2,3,4,5,6,7,8,9 private final static String[] nohs={"零","1","2","3","4","5","6","7","8","9"}; //0 1 2 3 4 5 6 7 8 9 private final static String[] noss={"0","1","2","3","4","5","6","7","8","9"}; // 寄存加减乘运算符 private final static char[] arr = {'+', '-', '×'}; //汉字加减乘运算符 private final static char[] arrh={'加','减','乘'}; private StringBuffer sb=null; private Random random=null; private int result; public int getResult(){ return result; } @Override protected void buildInitialFactories() { random = new Random(); sb=new StringBuffer(); //获得1个随机boolean boolean bool=random.nextBoolean(); //掉用生成运算模式方法 this.model(bool); int len=sb.toString().length(); WordGenerator wgen=new DummyWordGenerator(sb.toString()); //设置字体色彩 RandomRangeColorGenerator cgen = new RandomRangeColorGenerator(new int[]{0, 60}, new int[]{0, 60}, new int[]{0, 60}); // 文字显示的个数 TextPaster textPaster = new RandomTextPaster(len, len, cgen, true); //设置图片背景色彩 ColorGenerator colorGenerator = new RandomRangeColorGenerator(new int[]{200, 200}, new int[]{200, 200}, new int[]{200, 200}); // 图片的大小 BackgroundGenerator backgroundGenerator = new FunkyBackgroundGenerator(90, 28,colorGenerator); // 字体魄式 Font[] fontsList = new Font[]{new Font("宋体", 0, 10)}; // 文字的大小 FontGenerator fontGenerator = new RandomFontGenerator(18, 20, fontsList); //将文字写入到图片中 WordToImage wordToImage = new ComposedWordToImage(fontGenerator, backgroundGenerator, textPaster); this.addFactory(new GimpyFactory(wgen, wordToImage)); } private void model(boolean bool){ // 生成随机整数num1 int num1 = getRandomNum(); // 生成随机整数num2 int num2 = getRandomNum(); //随机产生运算方式 int operate = random.nextInt(3); switch (operate) { case 0: this.result = num1 + num2; break; case 1: this.result = num1 - num2; break; case 2: this.result = num1 * num2; break; } try{ //随机生成运算表达试 if(bool){ this.getRes(operate,num1,num2); }else{ int r=random.nextInt(3); sb.append(getNos(r,num1)+" "); r=random.nextInt(2); sb.append(getOperate(r,operate)+" "); r=random.nextInt(3); sb.append(getNos(r,num2)); sb.append(" = ?"); } }catch (Exception e){ e.printStackTrace(); } } //生成运算表达试 private void getRes(int operate,int num1,int num2){ int r=random.nextInt(2); switch (r){ case 0: r=random.nextInt(3); sb.append(getNos(r,num1)+" "); r=random.nextInt(2); sb.append(getOperate(r,operate)+" "); sb.append("?"); sb.append(" = "+this.result); this.result=num2; break; case 1: sb.append("? "); r=random.nextInt(2); sb.append(getOperate(r,operate)+" "); r=random.nextInt(3); sb.append(getNos(r,num2)); sb.append(" = "+this.result); this.result=num1; break; } } //获得运算数字 private String getNos(int random,int num) { switch (random){ case 0: return nods[num]; case 1: return nohs[num]; case 2: return noss[num]; } return null; } //获得运算符 private String getOperate(int random,int num){ switch (random){ case 0: return String.valueOf(arr[num]); case 1: return String.valueOf(arrh[num]); } return null; } //获得0~9随机数 private int getRandomNum(){ int num = random.nextInt(10); while (num == 0) { num = random.nextInt(10); } return num; } }

这里主要是为了构成用于计算结果的文字和图片和1些样式的设定。

3、测实验证码

servlet

package com.tgb.cfl; import com.octo.captcha.service.CaptchaServiceException; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * 用于生产验证码图片的class * @author cfl * @date 2015年4月30日 * */ public class VerificationCode extends HttpServlet { private static final long serialVersionUID = -11L; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { byte[] b = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { //获得session对象 HttpSession session=request.getSession(); //获得本次会话的sessionID String captchaId = session.getId(); //生成图片 BufferedImage challenge = BfferImageCss.getInstance().getImageChallengeForID(captchaId, request.getLocale()); //将结果保存到session session.setAttribute(captchaId+"_vccode",BfferImageCss.result); //加密 JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(baos); jpegEncoder.encode(challenge); } catch (IllegalArgumentException e) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } catch (CaptchaServiceException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } b = baos.toByteArray(); //设置相应的参数,用于显示图片 response.setHeader("Cache-Control", "no-store"); response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg"); ServletOutputStream sos = response.getOutputStream(); sos.write(b); sos.flush(); sos.close(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } }

这里是1个简单的servlet用于,虽然是1个简单的servlet,但是也足够完成所需功能。

好了,最后附上效果图1张

还是不错吧!

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐