- 为什么要学习验证码?
1、可以防止恶意破解密码、刷票、论坛灌水。
2、有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。
3、实际上用验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能。 - 验证码实现的方式
1、字母数字混合验证码
importjavax.imageio.ImageIO; importjavax.servlet.http.HttpServletResponse; importjava.awt.*; importjava.awt.font.FontRenderContext; importjava.awt.geom.Rectangle2D; importjava.awt.image.BufferedImage; importjava.util.Random;
/*** 此方法用户产生随机数-字母和数字* @return*/privatestaticcharrandomChar(){ //1:定义验证需要的字母和数字Stringstring="QWERTYUIOPASDFGHJKLZXCVBNM0123456789"; //2:定义随机对象Randomrandom=newRandom(); returnstring.charAt(random.nextInt(string.length())); }
/*** 字母数字混合验证码* @param response* @return*/publicstaticStringdrawImage(HttpServletResponseresponse){ //1:定义以字符串的拼接的StringBuilderStringBuilderbuilder=newStringBuilder(); //准备产生4个字符串的随机数for(inti=0;i<4;i++){ builder.append(randomChar()); } Stringcode=builder.toString(); //2:定义图片的宽度和高度intwidth=70; intheight=25; //简历bufferedImage对象,制定图片的长度和宽度以及色彩BufferedImagebi=newBufferedImage(width,height,BufferedImage.TYPE_3BYTE_BGR); //3:获取到 Graphics2D 绘制对象,开始绘制验证码Graphics2Dg=bi.createGraphics(); //4:设置文字的字体和大小Fontfont=newFont("微软雅黑",Font.PLAIN,20); //设置字体的颜色Colorcolor=newColor(0,0,0); //设置字体g.setFont(font); //设置颜色g.setColor(color); //设置背景g.setBackground(newColor(226,226,240)); //开始绘制对象g.clearRect(0,0,width,height); //绘制形状,获取矩形对象FontRenderContextcontext=g.getFontRenderContext(); Rectangle2Dbounds=font.getStringBounds(code,context); //计算文件的坐标和间距doublex= (width-bounds.getWidth())/2; doubley= (height-bounds.getHeight())/2; doubleascent=bounds.getY(); doublebaseY=y-ascent; g.drawString(code,(int)x,(int)baseY); //结束绘制g.dispose(); try { ImageIO.write(bi,"jpg",response.getOutputStream()); //刷新响应流response.flushBuffer(); }catch(Exceptionex){ ex.printStackTrace(); } returncode; }
// code.jsp<%@pageimport="com.imooc.code.CaptcahCode"%><%@pagecontentType="text/html;charset=UTF-8"language="java"%><%// 清空浏览器缓存,目的是为了清空浏览器的缓存,因为浏览器会对网站的资源文件和图像进行记忆存储,// 如果被浏览器加载过的图片就记忆起来,记忆以后,// 文件就不会和服务器在交互,如果我们验证不清空的话可能会造成一个问题就是:验证刷新以后没有效果。response.setHeader("pragma","no-cache"); response.setHeader("cache-control","no-cache"); response.setHeader("expires","0"); //2:调用编写的生成验证码的工具Stringcode=CaptcahCode.drawImage(response); session.setAttribute("code",code); //3:如何解决getOutputStream异常问题out.clear(); out=pageContext.pushBody(); %>
// index.jsp<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%><!DOCTYPEHTML><html><head><title>java验证码</title><metahttp-equiv="pragma"content="no-cache"><metahttp-equiv="cache-control"content="no-cache"><metahttp-equiv="expires"content="0"></head><body><imgsrc="code.jsp"alt=""id="code"><ahref="javascript:void(0);"onclick="changeCode()">看不清?点我</a><script>functionchangeCode() { document.getElementById("code").src="code.jsp?d="+newDate().getTime(); } </script></body></html>
2、算术验证码
importjavax.imageio.ImageIO; importjavax.servlet.http.HttpServletResponse; importjava.awt.*; importjava.awt.font.FontRenderContext; importjava.awt.geom.Rectangle2D; importjava.awt.image.BufferedImage; importjava.util.Random;
/*** 范围随机颜色* @param fc* @param bc* @return*/publicstaticColorgetRandomColor(intfc,intbc){ //利用随机数Randomrandom=newRandom(); //随机颜色,了解颜色-Color(red,green,blue).rgb三元色 0-255if(fc>255)fc=255; if(bc>255)bc=255; intr=fc+random.nextInt(bc-fc); intg=fc+random.nextInt(bc-fc); intb=fc+random.nextInt(bc-fc); returnnewColor(r,g,b); }
/*** 算术表达式验证码** 1:干扰线的产生* 2: 范围随机颜色,随机数** @param response* @return*/publicstaticStringdrawImageVerificate(HttpServletResponseresponse){ //定义验证码的宽度和高度intwidth=100,height=30; //在内存中创建图片BufferedImageimage=newBufferedImage(width,height,BufferedImage.TYPE_INT_RGB); //创建图片的上下文Graphics2Dg=image.createGraphics(); //产生随机对象,此随机对象主要用于算术表达式的数字Randomrandom=newRandom(); //设置背景g.setColor(getRandomColor(240,250)); //设置字体g.setFont(newFont("微软雅黑", Font.PLAIN,22)); //开始绘制g.fillRect(0,0,width,height); //干扰线的绘制,绘制线条到图片中g.setColor(getRandomColor(180,230)); for(inti=0;i<10;i++){ intx=random.nextInt(width); inty=random.nextInt(height); intx1=random.nextInt(60); inty1=random.nextInt(60); g.drawLine(x,y,x1,y1); } //开始进行对算术验证码表达式的拼接intnum1= (int)(Math.random()*10+1); intnum2= (int)(Math.random()*10+1); intfuhao=random.nextInt(3);//产生一个[0,2]之间的随机整数//记录符号Stringfuhaostr=null; intresult=0; switch (fuhao){ case0 : fuhaostr="+";result=num1+num2;break; case1: fuhaostr="-";result=num1-num2;break; case2 : fuhaostr="*";result=num1*num2;break; //case 3 : fuhaostr = "/";result = num1 / num2;break; } //拼接算术表达式,用户图片显示。Stringcalc=num1+" "+fuhaostr+" "+num2+" = ?"; //设置随机颜色g.setColor(newColor(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110))); //绘制表达式g.drawString(calc,5,25); //结束绘制g.dispose(); try { //输出图片到页面ImageIO.write(image,"JPEG",response.getOutputStream()); returnString.valueOf(result); }catch (Exceptionex){ ex.printStackTrace(); returnnull; } }
// code.jsp<%@pageimport="com.imooc.code.CaptcahCode"%><%@pagecontentType="text/html;charset=UTF-8"language="java"%><%// 清空浏览器缓存,目的是为了清空浏览器的缓存,因为浏览器会对网站的资源文件和图像进行记忆存储,// 如果被浏览器加载过的图片就记忆起来,记忆以后,// 文件就不会和服务器在交互,如果我们验证不清空的话可能会造成一个问题就是:验证刷新以后没有效果。response.setHeader("pragma","no-cache"); response.setHeader("cache-control","no-cache"); response.setHeader("expires","0"); //2:调用编写的生成验证码的工具Stringcode=CaptcahCode.drawImageVerificate(response); session.setAttribute("code",code); //3:如何解决getOutputStream异常问题out.clear(); out=pageContext.pushBody(); %>
// index.jsp<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%><!DOCTYPEHTML><html><head><title>java验证码</title><metahttp-equiv="pragma"content="no-cache"><metahttp-equiv="cache-control"content="no-cache"><metahttp-equiv="expires"content="0"></head><body><imgsrc="code.jsp"alt=""id="code"><ahref="javascript:void(0);"onclick="changeCode()">看不清?点我</a><script>functionchangeCode() { document.getElementById("code").src="code.jsp?d="+newDate().getTime(); } </script></body></html>
3、kcaptcha
// index.jsp<%@pagecontentType="text/html;charset=UTF-8"language="java"%><html><head><title>关于验证码框架之---Kaptcha</title></head><body><formaction="submit.action"><inputtype="text"name="kaptcha"value=""/><imgsrc="http://localhost:8080/imooccode/kaptcha.jpg"/></form></body></html>
// web.xml<?xmlversion="1.0"encoding="UTF-8"?><web-appxmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><!--关于kaptcha验证码的配置--><!--<servlet><servlet-name>Kaptcha</servlet-name><servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class></servlet><servlet-mapping><servlet-name>Kaptcha</servlet-name><url-pattern>/kaptcha.jpg</url-pattern></servlet-mapping>--><servlet><servlet-name>Kaptcha</servlet-name><servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class><init-param><param-name>kaptcha.border</param-name><param-value>no</param-value></init-param><init-param><param-name>kaptcha.image.width</param-name><param-value>100</param-value></init-param><init-param><param-name>kaptcha.image.height</param-name><param-value>40</param-value></init-param><init-param><param-name>kaptcha.textproducer.font.size</param-name><param-value>28</param-value></init-param><init-param><param-name>kaptcha.textproducer.char.string</param-name><param-value>qwertyuiopasdfghjklzxcvbnm123456789</param-value></init-param><init-param><param-name>kaptcha.textproducer.char.length</param-name><param-value>4</param-value></init-param><init-param><param-name>kaptcha.noise.impl</param-name><param-value>com.google.code.kaptcha.impl.DefaultNoise</param-value></init-param><init-param><param-name>kaptcha.obscurificator.impl</param-name><param-value>com.google.code.kaptcha.impl.FishEyeGimpy</param-value></init-param><init-param><!--session.setAttribute("kcode",生成好的验证码)--><param-name>kaptcha.session.key</param-name><param-value>kcode</param-value></init-param></servlet><servlet-mapping><servlet-name>Kaptcha</servlet-name><url-pattern>/kaptcha.jpg</url-pattern></servlet-mapping><servlet><servlet-name>LoginServlet</servlet-name><servlet-class>com.imooc.code.LoginServlet</servlet-class></servlet><servlet-mapping><servlet-name>LoginServlet</servlet-name><url-pattern>/login</url-pattern></servlet-mapping>--></web-app>
// 配置详情.txtKaptcha是一个基于SimpleCaptcha的验证码开源项目。官网地址:http://code.google.com/p/kaptcha/kaptcha的使用比较方便,只需添加jar包依赖之后简单地配置就可以使用了。kaptcha所有配置都可以通过web.xml来完成,如果你的项目中使用了SpringMVC,那么则有另外的一种方式来实现。一、简单的jsp-servlet项目1.添加jar包依赖如果你使用maven来统一管理jar包,则在工程的pom.xml中添加dependencyXml代码收藏代码<!--kaptcha--><dependency><groupId>com.google.code.kaptcha</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version></dependency>如果是非maven管理的项目,则直接在官网下载kaptcha的jar包,然后添加到项目lib库中,下载地址:http://code.google.com/p/kaptcha/downloads/list2.配置web.xml上面说了,kaptcha都是在web.xml中配置,我们必须在web.xml中配置kaptcha的servlet,具体如下: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><url-pattern>/kaptcha.jpg</url-pattern></servlet-mapping>其中servlet的url-pattern可以自定义。kaptcha所有的参数都有默认的配置,如果我们不显示配置的话,会采取默认的配置。如果要显示配置kaptcha,在配置kaptcha对应的Servlet时,在init-param增加响应的参数配置即可。示例如下:Xml代码收藏代码<servlet><servlet-name>Kaptcha</servlet-name><servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class><init-param><param-name>kaptcha.image.width</param-name><param-value>200</param-value><description>Widthinpixelsofthekaptchaimage.</description></init-param><init-param><param-name>kaptcha.image.height</param-name><param-value>50</param-value><description>Heightinpixelsofthekaptchaimage.</description></init-param><init-param><param-name>kaptcha.textproducer.char.length</param-name><param-value>4</param-value><description>Thenumberofcharacterstodisplay.</description></init-param><init-param><param-name>kaptcha.noise.impl</param-name><param-value>com.google.code.kaptcha.impl.NoNoise</param-value><description>Thenoiseproducer.</description></init-param></servlet>具体的配置参数参见:http://code.google.com/p/kaptcha/wiki/ConfigParametersConstant描述默认值kaptcha.border图片边框,合法值:yes , noyeskaptcha.border.color边框颜色,合法值:r,g,b (andoptionalalpha) 或者white,black,blue. blackkaptcha.border.thickness边框厚度,合法值:>01kaptcha.image.width图片宽200kaptcha.image.height图片高50kaptcha.producer.impl图片实现类com.google.code.kaptcha.impl.DefaultKaptchakaptcha.textproducer.impl文本实现类com.google.code.kaptcha.text.impl.DefaultTextCreatorkaptcha.textproducer.char.string文本集合,验证码值从此集合中获取abcde2345678gfynmnpwxkaptcha.textproducer.char.length验证码长度5kaptcha.textproducer.font.names字体Arial, Courierkaptcha.textproducer.font.size字体大小40pxkaptcha.textproducer.font.color字体颜色,合法值:r,g,b或者white,black,blue. blackkaptcha.textproducer.char.space文字间隔2kaptcha.noise.impl干扰实现类com.google.code.kaptcha.impl.DefaultNoisekaptcha.noise.color干扰颜色,合法值:r,g,b或者white,black,blue. blackkaptcha.obscurificator.impl图片样式:水纹com.google.code.kaptcha.impl.WaterRipple鱼眼com.google.code.kaptcha.impl.FishEyeGimpy阴影com.google.code.kaptcha.impl.ShadowGimpycom.google.code.kaptcha.impl.WaterRipplekaptcha.background.impl背景实现类com.google.code.kaptcha.impl.DefaultBackgroundkaptcha.background.clear.from背景颜色渐变,开始颜色lightgreykaptcha.background.clear.to背景颜色渐变,结束颜色whitekaptcha.word.impl文字渲染器com.google.code.kaptcha.text.impl.DefaultWordRendererkaptcha.session.keysessionkeyKAPTCHA_SESSION_KEYkaptcha.session.datesessiondateKAPTCHA_SESSION_DATE3.页面调用Html代码收藏代码<formaction="submit.action"><inputtype="text"name="kaptcha"value=""/><imgsrc="kaptcha.jpg"/></form>4.在submit的action方法中进行验证码校验Java代码收藏代码//从session中取出servlet生成的验证码text值StringkaptchaExpected= (String)request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); //获取用户页面输入的验证码StringkaptchaReceived=request.getParameter("kaptcha"); //校验验证码是否正确if (kaptchaReceived==null||!kaptchaReceived.equalsIgnoreCase(kaptchaExpected)){ setError("kaptcha", "Invalid validation code."); } 注:确保JDK设置了-Djava.awt.headless=true5.实现页面验证码刷新Html代码收藏代码<imgsrc="kaptcha.jpg"width="200"id="kaptchaImage"title="看不清,点击换一张"/><scripttype="text/javascript">$(function() { $('#kaptchaImage').click(function() {$(this).attr('src','kaptcha.jpg?'+Math.floor(Math.random() *100));}); }); </script><br/><small>看不清,点击换一张</small>
4、jcaptcha
- 了解验证码功能的实现与原理
4.kcaptcha 应用版(在2的kcaptcha的基础上)
// test.jsp<%--CreatedbyIntelliJIDEA. User: AdministratorDate: 2017/9/8Time: 21:10TochangethistemplateuseFile|Settings|FileTemplates. --%><%@pagecontentType="text/html;charset=UTF-8"language="java"%><html><head><title>登录</title><style>#code{height:30px;}</style></head><body><formaction="submit.action"><p><inputtype="text"name="kaptcha"id="code"value=""maxlength="4"placeholder="请输入验证码"/><imgsrc="http://localhost:8080/imooccode/kaptcha.jpg"id="changecode"/></p><p><inputtype="button"id="login"value="登录"></p><divid="result"></div></form><scriptsrc="js/jquery-1.12.4.min.js"type="text/javascript"></script><script>$(function(){ $("#changecode").on("click",function(){ $(this).attr("src","http://localhost:8080/imooccode/kaptcha.jpg?d="+newDate().getTime()); }); //给登录按钮绑定点击事件$("#login").on("click",function(){ //获取用户输入的验证码varcode=$("#code").val(); //alert(code);varparams= {"code":code}; $.post("http://localhost:8080/imooccode/login",params,function(data){ // if(data=="fail"){// alert("验证码输入有误!");// }if(data=="success"){ $("#result").html("验证码输入正确"); }else{ $("#result").html("验证码输入有误,请重新输入..."); $("#code").val("").focus(); } }); }); }) </script></body></html>
packagecom.imooc.code; importcom.google.code.kaptcha.Constants; importjavax.servlet.ServletException; importjavax.servlet.annotation.WebServlet; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importjava.io.IOException; importjava.io.PrintWriter; publicclassLoginServletextendsHttpServlet { publicvoiddoPost(HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException { //设置编码request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); //获取浏览器输出流对象PrintWriterout=response.getWriter(); //获取用户传递过来的验证码Stringcode=request.getParameter("code"); //获取验证码框架产生的验证码(会话中存储的验证码)StringsessionCode= (String)request.getSession().getAttribute("kcode"); if(code!=null&sessionCode!=null) { //如果用户输入的验证码和产生在服务器端的验证码一致,那么就告诉用户输入正确if (code.equalsIgnoreCase(sessionCode)) { //登录逻辑、注册逻辑等相关的业务操作out.print("success"); } else { out.print("fail"); } } out.flush(); out.close(); } publicvoiddoGet(HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException { this.doPost(request,response); } }
5.待更新...