浅尝Java验证码制作(上)

相信大家对验证码这玩意不会陌生,无论是申请账号还是某些情况下登录时都会要求输入验证码。经过统计,验证码一次验证就成功通过的概率是90%,并不高,那么很多人对于这种降低用户体验度的设计肯定会怀疑他的必要性,但黑格尔说过:凡是合乎理性的东西都是现实的;凡是现实的东西都是合乎理性的。接下来我们来了解一下验证码。

验证码是一种区别用户是计算机还是人的公共全自动程序,他被用于防止恶意破解密码、刷票、论坛灌水,防止黑客通过暴力破解方式不断地登录,应用于银行、社区、论坛、投票系统等等。

废话不多说我们来看看我已知的用Java实现验证码的四种方式。

方法一:

第一种方法是我最先想到的,也是实现逻辑最简单的,但效率、安全性极其不高。

具体操作就是:1、用photoshop制作出验证码图片,矩形图片上可有必要的英文字母、数字或中文(如上)

2、将图片显示在swing控件中或是jsp页面中

3、在代码中为每张图片匹配上相应的验证码字符串

4、在提交时获取组件或文本框中的字符串与每张图片的字符串用equals()方法进行比较

缺憾就是制作验证码图片的过程太费时,实现方法极low,极不推荐这样实现,下面的方法将越来越高效美观相对安全。

方法二:

这里讲Java Web,Servlet下的验证码实现,实现起来逻辑还是很清晰的。

省去较简单的实现代码,我们先从前台关键代码说起:

当我们点击"看不清"时,验证码图片会进行一个刷新,会调用一个js函数用于重新设置图片路径来更换图片,请看下面代码,代码中<%=request.getContextPath()%>是为了解决相对路径的问题,可返回站点的根路径,而/servlet/ImageServlet是一个整体,指向的就是ImageServlet这个servlet,为什么要在之前加个/servlet呢,因为我们在web.xml中做了配置映射,可理解为换了个更长的名称。接着看下面js函数,可能有些人会有疑问,为什么获取一个当前时间然后加在路径最后呢,其实这是为了解决浏览器缓存的问题,就是当触发了ImageServlet后虽然验证码图片换了但缓存还没变显示出来的验证码图片不变的问题,借助每时每刻时间不同可以让浏览器缓存失效。

1 <script type="text/javascript">
2        function reloadCode(){
3            var time = new Date().getTime();
4            document.getElementById("imagecode").src="<%=request.getContextPath() %>/servlet/ImageServlet?d="+time;
5        }
6 </script>

js函数

下面是web.xml中的关键配置信息:

 1     <servlet>
 2         <servlet-name>ImageServlet</servlet-name>
 3         <servlet-class>com.muke.ImageServlet</servlet-class>
 4     </servlet>
 5     <servlet>
 6         <servlet-name>LoginServlet</servlet-name>
 7         <servlet-class>com.muke.LoginServlet</servlet-class>
 8     </servlet>
 9     <servlet-mapping>
10         <servlet-name>ImageServlet</servlet-name>
11         <url-pattern>/servlet/ImageServlet</url-pattern>
12     </servlet-mapping>
13     <servlet-mapping>
14         <servlet-name>LoginServlet</servlet-name>
15         <url-pattern>/servlet/LoginServlet</url-pattern>
16     </servlet-mapping>    

web.xml

然后我们看关键的ImageServlet是怎么生成图片的:

 1 public class ImageServlet extends HttpServlet {
 2 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
 3         BufferedImage bi = new BufferedImage(68,22,BufferedImage.TYPE_INT_RGB);
 4         Graphics g = bi.getGraphics();
 5         Color c = new Color(200,150,255);
 6         g.setColor(c);
 7         g.fillRect(0, 0, 68, 22);
 8         char[] ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
 9         Random r = new Random();
10         int len=ch.length,index;
11         StringBuffer sb = new StringBuffer();
12         for(int i=0; i<4; i++){
13             index = r.nextInt(len);
14             g.setColor(new Color(r.nextInt(88),r.nextInt(188),r.nextInt(255)));
15             g.drawString(ch[index]+"", (i*15)+3, 18);
16             sb.append(ch[index]);
17         }
18         request.getSession().setAttribute("piccode", sb.toString());
19         ImageIO.write(bi, "JPG", response.getOutputStream());
20     }
21 }

ImageServlet

如果要更生动的描述这种验证码是怎么样来实现的,那么就一个字“画”,听上去和第一种方法类似,还是比较low,但是用代码来自动“画”出验证码效率绝对翻了无数倍。我们来看上述代码,首先实例化了一个BufferedImage对象bi,bi是用来画出那张验证码图片的,然后用bi得到一支画笔g,用g画出了实体的矩形背景,接着用简单的逻辑通过画笔g调用Java中常用的drawString()方法在矩形上画出验证码字符,同时将字符串依次加入StringBuffer可变字符串对象中,最后存入jsp内置对象session中以便提交验证码后的比对,为了显示出验证码,我们还需将生成验证码图片以某种图片格式写入ImageIO流。

下面LoginServlet中可以看出,获取刚刚ImageServlet存入session的字符串就可以进行与验证码提交框中字符串的比对了,可以把字符串都变为小写或大写做一个忽略大小写的处理。

 1 public class LoginServlet extends HttpServlet{
 2     public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
 3         String piccode = (String) request.getSession().getAttribute("piccode");
 4         String checkcode = request.getParameter("checkcode");
 5         checkcode = checkcode.toUpperCase();
 6         response.setContentType("text/html;charset=gbk");
 7         PrintWriter out = response.getWriter();
 8         if(checkcode.equals(piccode)){
 9             out.println("验证码输入正确!");
10         }else{
11             out.println("验证码输入错误!!!");
12         }
13         out.flush();
14         out.close();
15     }
16 }

LoginServlet

下面是实现图例:

//未完,见(下)http://www.cnblogs.com/justcaxzm/p/5494959.html

时间: 2024-11-08 19:26:29

浅尝Java验证码制作(上)的相关文章

浅尝Java验证码制作(下)

方法三: 用开源组件Jcaptcha实现,与Spring组合使用可产生多种形式的验证码,JCaptcha 即为 Java 版本的 CAPTCHA 项目,其是一个开源项目,支持生成图形和声音版的验证码,在生成声音版的验证码时,需要使用到 FreeTTS.而CAPTCHA 全称 Completely Automated Public Turing Test to Tell Computers and Humans Apart,最早作为卡内基梅隆大学的一个科研项目,用于生成一个人类容易通过而计算机难以

浅谈JAVA验证码~

这两天在帮同学做个项目,项目中需要做个验证码,说实话那么多年竟然没注意过这东西,原理很简单,贴出来给大家做个参考. 1.简单介绍 一般稍微有些经验的程序员都不会再自己写原生验证码生成了,因为各种强大的开源组件,足以解决我们大部分的需求.但是,毕竟也是刚接触这东西,还需要从原理入手的. 项目效果图: 下面我就简单介绍下原生和使用开源项目kaptcha生成验证码的两种形式. 2.jdk原生生成验证码 效果: 2.1 验证码生成的流程 1.定义BufferedImage(图像数据缓冲区)对象 2.获得

Java验证码的jar制作

Java验证码代码: package cn.itcast.image; import java.awt.BasicStroke;import java.awt.Color;import java.awt.Font;import java.awt.Graphics2D;import java.awt.image.BufferedImage;import java.io.IOException;import java.io.OutputStream;import java.util.Random;

浅尝ECMAScript6

浅尝ECMAScript6 简介 ECMAScript6 是最新的ECMAScript标准,于2015年6月正式推出(所以也称为ECMAScript 2015),相比于2009年推出的es5, es6定义了更加丰富的语言特性,基于该标准的Javascript语言也迎来了语法上的重大变革.本文列举了部分es6新特性,希望之前没接触es6的小伙伴读完本文能对下一代js编程有一个初步的认识. 箭头函数 箭头函数用 "=>"简化函数定义,类似于C#, Java8中的Lambda表达式,支

Python图形界面开发编程:wxPython(浅尝篇)

Python 提供了多个图形开发界面的库,几个常用 Python GUI 库如下: Tkinter: Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 .Tk 和 Tkinter 可以在大多数的 Unix 平台下使用,同样可以应用在 Windows 和 Macintosh 系统里.Tk8.0 的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中. wxPython:wxPython 是一款开源软件,是 Python 语言的一套优秀的 GUI 图形库,

来自后端的突袭? --开包即食的教程带你浅尝最新开源的C# Web引擎 Blazor

来自后端的突袭? --开包即食的教程带你浅尝最新开源的C# Web引擎 Blazor 在今年年初, 恰逢新春佳节临近的时候. 微软给全球的C#开发者们, 着实的送上了一分惊喜. 微软正式开源Blazor ,将.NET带回到浏览器. 这个小惊喜, 迅速的在dotnet开发者中间传开了. 而就在昨天(2018年3月22日) Blazor发布了它的第一次Release. Blazor到底是个什么样的东西呢?我们是否真的可以携着C#语言进入前端的市场中? 不如现在就跟我一起体验dotnet blazor

浅谈 Java Printing

浅谈 Java  Printing 其实怎么说呢?在写这篇博文之前,我对java printing 可以说是一无所知的.以至于我在敲文字时, 基本上是看着api文档翻译过来的.这虽然看起来非常的吃力,但是我相信,有道大哥不会辜负我的.嘻 嘻! Java Printing 技术,也就是我们平时所接触的打印,只不过是说可以用Java实现而已. 一.Java Printing 打印简介 Java Printing API能够使java应用程序实现相关的打印功能,如: 1.打印所有 Java 2D 和

【转】浅谈Java中的equals和==

浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str2 = new String("hello"); 3 4 System.out.println(str1==str2); 5 System.out.println(str1.equals(str2)); 为什么第4行和第5行的输出结果不一样?==和equals方法之间的区别是什么?如果在初

Java验证码和ajax判断

关于来了解相关的api BufferedImage(int width, int height, int imageType) 构造一个类型为预定义图像类型之一的 BufferedImage. BufferedImage 描述具有可访问图像数据缓冲区的Image 字段摘要(TYPE_INT_RGB)表示一个图像,它具有合成整数像素的 8 位 RGB 颜色分量. getGraphics() 此方法返回 Graphics2D(Graphics2D 类扩展 Graphics 类,以提供对几何形状.坐标