这个是我按照慕课网上的教程一步步走下来的流程,这里做个小记录。
------------------------------------------------------------------------------------
1。验证码概述
CAPTCHA--Completely Automated Public Turing Test to Tell Computers and Humans Apart (全自动区分计算机和人类的图灵测试)的简称
验证码的定义:验证码是一种区分用户是计算机还是人的公共自动程序---降低用户体验度
作用:可以防止恶意破解密码,刷票,论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试
另外,翻到一个谈到很多类型验证码的帖子,有一定参考性,也放上来:
http://www.iteye.com/topic/1054760
2。使用servlet实现验证码
验证码包含两部分:1.输入框
2.显示验证码的图片
前端的实现如下,img的src我们指向的是一个servlet,这样就可以实时的生成
<form action="<%=request.getContextPath()%>/servlet/LoginServlet" method="post">
username:<input type="text" name="username"/><br>
password:<input type="password" name="pwd"/><br>
验证码:<input type="text" id="verifyCode" name="verifyCode" size="6"/>
<img alt="验证码" id="safecode" src="<%=request.getContextPath()%>/servlet/ImageServlet"/></span>
<a href="javascript:reloadCode();">看不清楚</a><br>
<input type="submit" value="login"/>
<input type="reset" value="reset"/>
</form>
<script type="text/javascript">
<span style="white-space:pre"> </span>function reloadCode(){
var time=new Date().getTime();
document.getElementById("safecode").src="<%=request.getContextPath()%>/servlet/ImageServlet<span style="color: rgb(255, 0, 0);">?d="+time;
<!--注意:这里传个time是必要的,不然刷新不出来,因为缓存会认为是同一个请求-->
}
</script>
生成图片用到的类:
1.BufferedImage图像数据缓冲区
2.Graphics 绘制图片
3.Color获取颜色
4.Random生成随机数
5.ImageIO输出图片
生成图片的实现类ImageServlet类:
1.定义BufferedImage对象
2.获得Graphics对象
3.通过Random产生随机验证码信息
4.使用Graphics绘制图片
5.记录验证码信息到session中
6.使用ImageIO输出图片
package com.whu.controller;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ImageServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException{
BufferedImage bi=new BufferedImage(68,22,BufferedImage.TYPE_INT_RGB);
Graphics g=bi.getGraphics();
Color c=new Color(200,150,255);
g.setColor(c);
g.fillRect(0, 0, 68, 22);
char[] ch="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
Random r=new Random();
int len=ch.length,index;
StringBuffer sb=new StringBuffer();
for(int i=0;i<4;i++){
index =r.nextInt(len);
g.setColor(new Color(r.nextInt(88),r.nextInt(188),r.nextInt(255)));
g.drawString(ch[index]+"", (i*15)+3, 18);
sb.append(ch[index]);
}
request.getSession().setAttribute("piccode", sb.toString());
ImageIO.write(bi, "JPG", response.getOutputStream());
}
}
校验验证码是否正确LoginServlet类:
1.获取页面验证码
2.获取session保存的验证码
3.比较验证码
4.返回校验结果
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html,charset=utf-8");
String piccode=(String) request.getSession().getAttribute("piccode");
String checkcode=request.getParameter("verifyCode");
checkcode=checkcode.toUpperCase();
if(checkcode.equals(piccode)){
String username=request.getParameter("username");
String pwd=request.getParameter("pwd");
User user=new User();
user.setUsername(username);
user.setPwd(pwd);
request.setAttribute("user",user);
request.getRequestDispatcher("/servlet/loginService").forward(request, response);
}
else{
request.getRequestDispatcher("../index.jsp").forward(request, response);
}
}
3.使用开源组件实现验证码--添加了噪点防止机器识别
1.Jcaptcha:一个用来生成图形验证码的JAVA开源组件,使用起来很方便,与spring组合使用,可以产生多种形式的验证码
2.Kaptcha:一个非常实用的验证码生成工具,有了它,你可以生成各种样式的验证码,因为它是可配置的。慕课的老师说这个比Jcaptcha更友好。。
1.Jcaptcha组件实现验证码:
这个慕课网上只讲了下载war包改改直接跑,关于war,jar什么的请看这里:war包和jar包
我比较懒,只看了Kaptcha,这里放几个链接上来要用了再看。
http://blog.csdn.net/tender001/article/details/8469698
2.Kaptcha组件实现验证码
kaptcha工作的原理是调用 com.google.code.kaptcha.servlet.KaptchaServlet,生成一个图片。同时将生成的验证码字符串放到 HttpSession中。
使用kaptcha可以方便的配置:
- 验证码的字体
- 验证码字体的大小
- 验证码字体的字体颜色
- 验证码内容的范围(数字,字母,中文汉字!)
- 验证码图片的大小,边框,边框粗细,边框颜色
- 验证码的干扰线(可以自己继承com.google.code.kaptcha.NoiseProducer写一个自定义的干扰线)
- 验证码的样式(鱼眼样式、3D、普通模糊……当然也可以继承com.google.code.kaptcha.GimpyEngine自定义样式)
----------------------------------------------------------------------------------------
实现步骤
· 下载kaptcha-2.3.jar
· 将jar包导入项目
· 编写页面
· 配置web.xml
· 启动项目
1。下载kaptcha-2.3jar
我在csdn上找了一个下载,解压后是这样的
2。将jar包导入项目
视频上老师的动作是将kaptcha-2.3.2.jar拷贝到项目的WebRoot/WEB-INF/lib下,jar就进入Referrenced Libraries,但是我这里变成了Web App Libraries,如下左图。
于是我只能 项目-》属性-》java build path-》Libraries-》add external JARs,把jar导入,入下右图。
3 。配置web.xml
<servlet>
<servlet-name>Kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Kaptcha</servlet-name>
<span style="color:#ff0000;"><strong><url-pattern>/kaptcha.jpg</url-pattern></strong></span>
</servlet-mapping>
4 。编写页面
<body>
<img src="kaptcha.jpg"> <!--注意:这里的src一定不能带“/”!!!这个src指向kaptcha这个servlet-->
This is my JSP page. <br>
</body>
5 。启动项目
成功。
-----------------------------------------------------------------------------------------------------------------------------------
6 。下面我们再来完善这个功能
在index.jsp中添加输入
<form action="check.jsp" >
<img src="kaptcha.jpg">
<input type="text" name="r"/>
<input type='submit'>
</form>
添加check.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
//检查是否是正确的验证码
String k=(String)session.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
String str=request.getParameter("r");
if(k.equals(str))
out.println("true");
out.print(k+"---"+str);
%>
运行成功。
7.接下来我们看看Kaptcha的详细配置
<servlet>
<servlet-name>Kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
<init-param>
<description>图片边框,合法值:yes,no</description>
<param-name>kaptcha.border</param-name>
<param-value>yes</param-value>
</init-param>
<init-param>
<description>边框颜色,合法值:white,black,blue等</description>
<param-name>kaptcha.border.color</param-name>
<param-value>blue</param-value>
</init-param>
<init-param>
<description>边框厚度,合法值:>0</description>
<param-name>kaptcha.border.thickness</param-name>
<param-value>5</param-value>
</init-param>
<init-param>
<description>图片宽度</description>
<param-name>kaptcha.image.width</param-name>
<param-value>600</param-value>
</init-param>
<init-param>
<description>图片高度</description>
<param-name>kaptcha.image.height</param-name>
<param-value>100</param-value>
</init-param>
<init-param>
<description>图片实现类</description>
<param-name>kaptcha.producer.impl</param-name>
<param-value>com.google.code.kaptcha.impl.DefaultKaptcha</param-value>
</init-param>
<init-param>
<description>文本实现类</description>
<param-name>kaptcha.textproducer.impl</param-name>
<param-value>com.google.code.kaptcha.text.impl.DefaultTextCreator</param-value>
</init-param>
<init-param>
<description>文本集,验证码值从此几何获得</description>
<param-name>kaptcha.textproducer.char.string</param-name>
<param-value>abcde2345678gfynmnpwx</param-value>
</init-param>
<init-param>
<description>字体Arial,courier</description>
<param-name>kaptcha.textproducer.font.names</param-name>
<param-value>Arial,Courier,宋体,楷体,微软雅黑</param-value>
</init-param>
<init-param>
<description>字体大小</description>
<param-name>kaptcha.textproducer.font.size</param-name>
<param-value>40</param-value>
</init-param>
<init-param>
<description>干扰实现类</description>
<param-name>kaptcha.noise.impl</param-name>
<param-value>com.google.code.kaptcha.impl.DefaultNoise</param-value>
</init-param>
<init-param>
<description>图片样式:水纹,鱼眼,阴影</description>
<param-name>kaptcha.obscurificator.impl</param-name>
<param-value>com.google.code.kaptcha.impl.WaterRipple</param-value>
</init-param>
<init-param>
<description>背景实现类</description>
<param-name>kaptcha.background.impl</param-name>
<param-value>com.google.code.kaptcha.impl.DefaultBackground</param-value>
</init-param>
<init-param>
<description>背景渐变色</description>
<param-name>kaptcha.background.clear.from</param-name>
<param-value>green</param-value>
</init-param>
<init-param>
<description>背景渐变色</description>
<param-name>kaptcha.background.clear.to</param-name>
<param-value>gray</param-value>
</init-param>
<init-param>
<description>文字渲染器</description>
<param-name>kaptcha.word.impl</param-name>
<param-value>com.google.code.kaptcha.text.impl.DefaultWordRenderer</param-value>
</init-param>
<init-param>
<description>The value for the kaptcha is generated and is put into the HttpSession. This is the key value for that item in the session. </description>
<param-name>kaptcha.session.key</param-name>
<param-value>KAPTCHA_SESSION_KEY</param-value>
</init-param>
<init-param>
<description>The date the kaptcha is generated is put into the HttpSession. This is the key value for that item in the session. </description>
<param-name>kaptcha.session.date</param-name>
<param-value>KAPTCHA_SESSION_DATE</param-value>
</init-param>
</servlet>
成功
8.除了这些以外还有跟spring结合,跟jQuery结合。
暂时够用我就不继续看了,放个跟spring结合的链接上来:http://stone02111.iteye.com/blog/1688195
9.中文验证码的制作
1.新建类ChineseText.java
package com.google.code.kaptcha.text;
import java.util.Random;
import com.google.code.kaptcha.text.TextProducer;
import com.google.code.kaptcha.util.Configurable;
public class ChineseText extends Configurable implements TextProducer{
public String getText() {
int length=getConfig().getTextProducerCharLength();
String finalWord="",firstWord="";
int tempInt=0;
String[] array={"0","1","2","3","4","5","6","7","8","9", "a","b","c","d","e","f"};
Random rand=new Random();
for(int i=0;i<length;i++){
switch(rand.nextInt(array.length)){
case 1:
tempInt=rand.nextInt(26)+65;
firstWord=String.valueOf((char)tempInt);
break;
case 2:
int r1,r2,r3,r4;
String strH,strL; //high&low
r1=rand.nextInt(3)+11; //[11,14)
if(r1==13){
r2=rand.nextInt(7);
}else{
r2=rand.nextInt(16);
}
r3=rand.nextInt(6)+10;
if(r3==10){
r4=rand.nextInt(15)+1;
}else if(r3==15){
r4=rand.nextInt(15);
}else{
r4=rand.nextInt(16);
}
strH=array[r1]+array[r2];
strL=array[r3]+array[r4];
byte[] bytes=new byte[2];
bytes[0]=(byte) Integer.parseInt(strH,16);
bytes[1]=(byte) Integer.parseInt(strL, 16);
firstWord=new String(bytes);
break;
default:
tempInt=rand.nextInt(10)+48;
firstWord=String.valueOf((char)tempInt);
break;
}
finalWord+=firstWord;
}
return finalWord;
}
}
以上代码是我直接抄了老师的代码,我自己看不懂。。。。==!有同学能看懂欢迎指教~
2.修改web.xml
<init-param>
<description>文本实现类</description>
<param-name>kaptcha.textproducer.impl</param-name>
<param-value>com.google.code.kaptcha.text.ChineseText</param-value>
</init-param>
3.运行结果能出现中文但是某些汉字显示不出来!!!
而提交后chrome是能显示那些汉字的!我也不知道怎么改!希望知道的同学能指导下
10.算式验证码的实现
实现步骤:
1.获取随机数值,结果相加
String s1=capText.substring(0,1);
String s2=capText.substring(1,2);
int r=Integer.valueOf(s1).intValue()+Integer.valueOf(s2).intValue();
2.将计算公式写到验证码图片中
BufferedImage bi=this.kaptchaProducer.createImage(s1+"+"+s2+"=?");
3.将相加结果放到session中
int r=Integer.valueOf(s1).intValue()+Integer.valueOf(s2).intValue();
req.getSession().setAttribute(this.sessionKeyValue,String.valueOf(r));
所以我们需要重写KaptchaServlet类
下面就开始吧~
-----------------------------------------------------------------------------------------
1.反编译com.google.code.kaptcha.servlet.KaptchaServlet
我用的工具是:http://download.csdn.net/download/suixingbugai/4145221
用它打开我们之前下的jar包
2.新建KaptchaServlet类,将我们刚刚反编译的KaptchaServlet拷贝过去再改一改。代码如下。
package com.google.code.kaptcha.text;
import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.util.Config;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import javax.imageio.ImageIO;
import javax.servlet.Servlet;
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;
public class KaptchaServlet extends HttpServlet
implements Servlet
{
private Properties props = new Properties();
private Producer kaptchaProducer = null;
private String sessionKeyValue = null;
private String sessionKeyDateValue = null;
public void init(ServletConfig conf)
throws ServletException
{
super.init(conf);
ImageIO.setUseCache(false);
Enumeration initParams = conf.getInitParameterNames();
while (initParams.hasMoreElements())
{
String key = (String)initParams.nextElement();
String value = conf.getInitParameter(key);
this.props.put(key, value);
}
Config config = new Config(this.props);
this.kaptchaProducer = config.getProducerImpl();
this.sessionKeyValue = config.getSessionKey();
this.sessionKeyDateValue = config.getSessionDate();
}
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
resp.setDateHeader("Expires", 0L);
resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
resp.addHeader("Cache-Control", "post-check=0, pre-check=0");
resp.setHeader("Pragma", "no-cache");
resp.setContentType("image/jpeg");
String capText = this.kaptchaProducer.createText();
String s1=capText.substring(0,1);
String s2=capText.substring(1,2);
int r=Integer.valueOf(s1).intValue()+Integer.valueOf(s2).intValue();
req.getSession().setAttribute(this.sessionKeyValue,String.valueOf(r));
BufferedImage bi=this.kaptchaProducer.createImage(s1+"+"+s2+"=?");
//req.getSession().setAttribute(this.sessionKeyValue, capText);
req.getSession().setAttribute(this.sessionKeyDateValue, new Date());
//BufferedImage bi = this.kaptchaProducer.createImage(capText);
ServletOutputStream out = resp.getOutputStream();
ImageIO.write(bi, "jpg", out);
try{
out.flush();
}finally{
out.close();
}
}
}
最后我们修改web.xml
<servlet>
<servlet-name>Kaptcha</servlet-name>
<!--<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class> -->
<servlet-class>com.google.code.kaptcha.text.KaptchaServlet</servlet-class>
<span style="white-space:pre"> </span><init-param>
<span style="white-space:pre"> </span><description>验证码长度</description>
<span style="white-space:pre"> </span><param-name>kaptcha.textproducer.char.length</param-name>
<span style="white-space:pre"> </span><param-value>2</param-value>
<span style="white-space:pre"> </span></init-param>
成功~~