通常來說一個B/S項目基本都會用到驗證碼,用於用戶登錄或註冊,以此提高項目的安全性,而目前仍存在一些網站的應用環境比較特殊,使用人羣分部較廣,所以需要考慮ie瀏瀏覽器的兼容性,衆所周知,ie一代比一代坑,9以下和9以上差異非常大,第三方驗證碼都很少有兼容ie9以下的。然而由於國情的特殊,仍然有一大部分人在使用ie8甚至更低版本的瀏覽器。所以我用了patcha,這是一款兼容ie7以上所有版本 (7以下沒做測試)的驗證碼jar包,接入非常方便,效果也不錯。
首先,servlet中的代碼
package org.captcha.servlet;
import java.awt.Color;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.patchca.color.ColorFactory;
import org.patchca.color.SingleColorFactory;
import org.patchca.filter.predefined.CurvesRippleFilterFactory;
import org.patchca.filter.predefined.DiffuseRippleFilterFactory;
import org.patchca.filter.predefined.DoubleRippleFilterFactory;
import org.patchca.filter.predefined.MarbleRippleFilterFactory;
import org.patchca.filter.predefined.WobbleRippleFilterFactory;
import org.patchca.service.ConfigurableCaptchaService;
import org.patchca.utils.encoder.EncoderHelper;
import org.patchca.word.RandomWordFactory;
public class CaptchaServlet extends HttpServlet {
private static final long serialVersionUID = 4968328161261528097L;
private static ConfigurableCaptchaService cs = null;
private static ColorFactory cf = null;
private static RandomWordFactory wf = null;
private static Random r = new Random();
private static CurvesRippleFilterFactory crff = null;
private static MarbleRippleFilterFactory mrff = null;
private static DoubleRippleFilterFactory drff = null;
private static WobbleRippleFilterFactory wrff = null;
private static DiffuseRippleFilterFactory dirff = null;
/**驗證碼字符串長度,默認4*/
private static Integer randomCodeLength=4;
/**驗證碼圖片寬度,默認120*/
private static Integer randomCodeWidth=120;
/**驗證碼圖片高度,默認50*/
private static Integer randomCodeHight=50;
/**驗證碼樣式
* 1 彎曲狀
* 2 搖擺裝
* 3 搖晃
* 4 散開
* 5 大理石
* 6 隨機(默認)
* */
private static Integer randomCodeType=6;
/**驗證碼session中Attribute的Name*/
private static String randomCodeSessionAttributeName="PATCHCA";
@Override
public void init() throws ServletException {
super.init();
cs = new ConfigurableCaptchaService();
cf = new SingleColorFactory(new Color(25, 60, 170));
wf = new RandomWordFactory();
crff = new CurvesRippleFilterFactory(cs.getColorFactory());
drff = new DoubleRippleFilterFactory();
wrff = new WobbleRippleFilterFactory();
dirff = new DiffuseRippleFilterFactory();
mrff = new MarbleRippleFilterFactory();
cs.setWordFactory(wf);
cs.setColorFactory(cf);
cs.setWidth(randomCodeWidth);
cs.setHeight(randomCodeHight);
randomCodeLength=Integer.valueOf(null==this.getInitParameter("randomCodeLength")?"4":this.getInitParameter("randomCodeLength"));
randomCodeWidth=Integer.valueOf(null==this.getInitParameter("randomCodeWidth")?"120":this.getInitParameter("randomCodeWidth"));
randomCodeHight=Integer.valueOf(null==this.getInitParameter("randomCodeHight")?"50":this.getInitParameter("randomCodeHight"));
randomCodeType=Integer.valueOf(null==this.getInitParameter("randomCodeType")?"6":this.getInitParameter("randomCodeType"));
randomCodeSessionAttributeName=null==this.getInitParameter("randomCodeSessionAttributeName")?"PATCHCA":this.getInitParameter("randomCodeSessionAttributeName");
}
@Override
public void destroy() {
wf = null;
cf = null;
cs = null;
super.destroy();
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("image/png");
response.setHeader("cache", "no-cache");
wf.setMaxLength(randomCodeLength);
wf.setMinLength(randomCodeLength);
HttpSession session = request.getSession(true);
OutputStream os = response.getOutputStream();
int typeCode=randomCodeType;
if(typeCode==6)
{
typeCode=r.nextInt(5);
}
//隨機產生5種效果(filter)
switch (typeCode) {
case 1:
cs.setFilterFactory(crff);
break;
case 2:
cs.setFilterFactory(mrff);
break;
case 3:
cs.setFilterFactory(drff);
break;
case 4:
cs.setFilterFactory(wrff);
break;
case 5:
cs.setFilterFactory(dirff);
break;
default:
cs.setFilterFactory(crff);
break;
}
//這裏可以生成彩色驗證碼
/* final Random random = new Random();
cs.setColorFactory(new SingleColorFactory(new Color(25, 60, 170)));
cs.setColorFactory(new ColorFactory() {
@Override
public Color getColor(int x) {
int[] c = new int[3];
int i = random.nextInt(c.length);
for (int fi = 0; fi < c.length; fi++) {
if (fi == i) {
c[fi] = random.nextInt(71);
} else {
c[fi] = random.nextInt(256);
}
}
return new Color(c[0], c[1], c[2]);
}
});*/
String patchca= EncoderHelper.getChallangeAndWriteImage(cs, "png", os);
session.setAttribute(randomCodeSessionAttributeName, patchca);
os.flush();
os.close();
}
}
web.xml中的配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>patchattest</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>patchca</servlet-name>
<servlet-class>org.captcha.servlet.CaptchaServlet</servlet-class>
<init-param><param-name>randomCodeType</param-name><param-value>3</param-value></init-param>
</servlet>
<servlet-mapping>
<servlet-name>patchca</servlet-name>
<url-pattern>/patchca.png</url-pattern>
</servlet-mapping>
</web-app>
jsp中的代碼,注意點擊事件後面跟的隨機數,用於改變圖片url防止瀏覽器緩存不清,點擊時重點內容圖片不變動。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
This is my JSP page. <br>
<table><tr>
<!-- patchca.png和servlet中的<url-pattern>對應 -->
<td><img src="patchca.png" alt="驗證碼"
style="cursor:pointer;vertical-align:text-bottom;"
onclick="this.src=this.src+'?'+Math.random();"></td>
<td valign="top">
<form method="POST">
<br>
驗證碼:<input type="text" name="patchcafield">
<br />
<input type="submit" name="submit">
</form></td></tr></table>
<br /><br /><br /><br />
</body>
</html>
效果
上面這種方式原生serlvlet的寫法應該沒人用了,現在都是用框架,這更加簡單,不需要任何配置,這邊用struts
action中的代碼,action返回的結果是一個圖片流,頁面上直接用img標籤可以接收到。
import java.awt.Color;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.patchca.color.ColorFactory;
import org.patchca.color.SingleColorFactory;
import org.patchca.filter.predefined.CurvesRippleFilterFactory;
import org.patchca.filter.predefined.DiffuseRippleFilterFactory;
import org.patchca.filter.predefined.DoubleRippleFilterFactory;
import org.patchca.filter.predefined.MarbleRippleFilterFactory;
import org.patchca.filter.predefined.WobbleRippleFilterFactory;
import org.patchca.service.ConfigurableCaptchaService;
import org.patchca.utils.encoder.EncoderHelper;
import org.patchca.word.RandomWordFactory;
import com.jshop.action.backstage.base.BaseTAction;
import com.opensymphony.xwork2.ActionContext;
@Namespace("/frontstage/buyers")
@ParentPackage("jshop")
public class CaptchaAction extends BaseTAction{
/**
*patchca驗證碼
*@author tang
*/
private static final long serialVersionUID = 1L;
private static ConfigurableCaptchaService cs = null;
private static ColorFactory cf = null;
private static RandomWordFactory wf = null;
private static Random r = new Random();
private static CurvesRippleFilterFactory crff = null;
private static MarbleRippleFilterFactory mrff = null;
private static DoubleRippleFilterFactory drff = null;
private static WobbleRippleFilterFactory wrff = null;
private static DiffuseRippleFilterFactory dirff = null;
/**驗證碼字符串長度,默認4*/
private static Integer randomCodeLength=4;
/**驗證碼圖片寬度,默認120*/
private static Integer randomCodeWidth=120;
/**驗證碼圖片高度,默認50*/
private static Integer randomCodeHight=50;
/**驗證碼樣式
* 1 彎曲狀
* 2 搖擺裝
* 3 搖晃
* 4 散開
* 5 大理石
* 6 隨機(默認)
* */
private static Integer randomCodeType=6;
/**驗證碼session中Attribute的Name*/
private static String randomCodeSessionAttributeName="PATCHCA";
/**
* 生成驗證碼
* @author tang
* @throws IOException
*/
@Action("/getCaptcha")
public void getCaptcha(){
cs = new ConfigurableCaptchaService();
cf = new SingleColorFactory(new Color(25, 60, 170));
wf = new RandomWordFactory();
crff = new CurvesRippleFilterFactory(cs.getColorFactory());
drff = new DoubleRippleFilterFactory();
wrff = new WobbleRippleFilterFactory();
dirff = new DiffuseRippleFilterFactory();
mrff = new MarbleRippleFilterFactory();
cs.setWordFactory(wf);
cs.setColorFactory(cf);
cs.setWidth(randomCodeWidth);
cs.setHeight(randomCodeHight);
randomCodeLength=Integer.valueOf(randomCodeLength);
randomCodeWidth=Integer.valueOf(randomCodeWidth);
randomCodeHight=Integer.valueOf(randomCodeHight);
randomCodeType=Integer.valueOf(randomCodeType);
randomCodeSessionAttributeName=null==randomCodeSessionAttributeName?"PATCHCA":randomCodeSessionAttributeName;
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("image/png");
response.setHeader("cache", "no-cache");
wf.setMaxLength(randomCodeLength);
wf.setMinLength(randomCodeLength);
OutputStream os;
try {
os = response.getOutputStream();
int typeCode=randomCodeType;
if(typeCode==6)
{
typeCode=r.nextInt(5);
}
//隨機產生5種效果(filter)
switch (typeCode) {
case 1:
cs.setFilterFactory(crff);
break;
case 2:
cs.setFilterFactory(mrff);
break;
case 3:
cs.setFilterFactory(drff);
break;
case 4:
cs.setFilterFactory(wrff);
break;
case 5:
cs.setFilterFactory(dirff);
break;
default:
cs.setFilterFactory(crff);
break;
}
final Random random = new Random();
cs.setColorFactory(new SingleColorFactory(new Color(25, 60, 170)));
cs.setColorFactory(new ColorFactory() {
@Override
public Color getColor(int x) {
int[] c = new int[3];
int i = random.nextInt(c.length);
for (int fi = 0; fi < c.length; fi++) {
if (fi == i) {
c[fi] = random.nextInt(71);
} else {
c[fi] = random.nextInt(256);
}
}
return new Color(c[0], c[1], c[2]);
}
});
String patchca= EncoderHelper.getChallangeAndWriteImage(cs, "png", os);
System.out.println(patchca);
if(os!=null){
os.close();
}
ActionContext.getContext().getSession().put(randomCodeSessionAttributeName, patchca);
}catch(Exception e){
System.err.println("遠程主機關閉了一個現有的鏈接");
}
}
}
html代碼
<img id="patchca" src="getCaptcha.action" alt="驗證碼" style="cursor:pointer;vertical-align:text-bottom;"onclick="this.src=this.src+'?random='+Math.random();"/>
大小,顏色,樣式都可以根據自己需要調整,用的都是awt下的Color類(好冷門的GUI的東西)
總結一下patcha的優點:全瀏覽器兼容、低依賴整合方便、安全性足夠,響應速度很快。
用到的jar包,也是唯一的一個jar包
http://download.csdn.net/detail/qq_36289377/9887404