前兩天買了張火車票,使人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.最后則是驗證的進程
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張