欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

验证码机制实现 博客分类: java ServletSwingJavaScriptSUN工作

程序员文章站 2024-03-18 18:16:22
...
我们经常在登陆一些网站的时候,要求输入显示的验证码,而且验证码是以图片形式提供,这是怎么实现的?HOHO,我也来实现一个。有兴趣的看看,也算做自己的笔记。

        你可能也猜想过验证码的图片不至于是预先做好了放在某个文件夹里的吧?NO,NO,试想,真的如此做的话,如果是4位验证码,并且字母数字混杂的话,这样的工作量美工肯定不接受:)所以,唯一的解释就是这些图片都是程序生成的。也就是程序“画”出来的!如何画?请看一段代码:

   int width=40, height=20;
   BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
   Graphics g = image.getGraphics();
   //以下填充背景颜色
   g.setColor(Color.decode("#66CCCF"));
   g.fillRect(0, 0, width, height);
   g.setColor(Color.decode("#01556B"));
   g.drawString(req.getParameter("yzm"),5,15);
   g.dispose();  



这段代码摘自我要举的例子。我想玩过applet和swing的朋友应该不难理解。我们把页面传过来的(req.getParameter("yzm")“画”在一个40,20大小的矩形框内。这段代码当然要放一个servlet里面,这个servlet就是来负责画图的:

import java.io.IOException;
import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.*;
import javax.servlet.ServletContext;
import java.io.OutputStream;
import java.awt.*;
import java.awt.image.*;
import com.sun.image.codec.jpeg.*;

/**
* @version  1.0
* @author dennis
*/
public class Getshowimg extends HttpServlet {

public void service(HttpServletRequest req, HttpServletResponse resp)
  throws ServletException, IOException {
  
   resp.setContentType("image/jpeg;charset=gb2312");
   int width=40, height=20;
   BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
   Graphics g = image.getGraphics();
   //以下填充背景颜色
   g.setColor(Color.decode("#66CCCF"));
   g.fillRect(0, 0, width, height);
   g.setColor(Color.decode("#01556B"));
   g.drawString(req.getParameter("yzm"),5,15);
   g.dispose();   
   OutputStream toClient = resp.getOutputStream();
   JPEGImageEncoder encoder =JPEGCodec.createJPEGEncoder(toClient);
   encoder.encode(image);
            toClient.close();
  }
}



好了,图已经知道怎么画了,接下来的问题就是我们怎么在页面上显示这个图?这个图同样也是个image,当然放在一个img元素里面。另外,我们应该在页面每一次刷新时都显示不同的验证码,所以应该在body的onload的事件里调用上面的servlet。来了,首先是页面:

验证码:<input name="yzm" type="text" size="12" onKeyPress="dojudge()" id="yzm0"></td>
  <div id="yzm1" style="width:10" style="display:none"></div><IMG src='servlet/Getshowimg?yzm=0' id="img0" vspace=3>

为什么要有个ID为yzm1的隐藏层??你可能要问。试想,我们如何判断用户输入的验证码和图片的一样呢?我们要读取text里输入的验证码,我们如何读取图片显示的验证码呢??这就是隐藏层的价值所在,我们把随机生成的验证码分成两份,一份保存在隐藏层里,一份传到servlet。判断的时候,我们根本不需要知道图片显示什么,图片显示的跟隐藏层的里一样!我们只要把隐藏层里的值与text里的值判断就OK了。javascript的doinit()函数,被body的onload事件调用:

function doinit()
{
document.form1.username.focus();
var tmp=Math.random();
while (true)
{
  if (tmp>=0.1)
  {
    var num=Math.round(tmp*10000);
    document.getElementById("yzm1").innerHTML="<font color='#01556B'>"+num+"</font>";
    document.getElementById("img0").src="servlet/Getshowimg?yzm="+num;
break;
  }else
    tmp=Math.random();
}

}
在登陆按钮中加入事件,判断输入是否正确:
if (document.form1.yzm.value!=document.getElementById("yzm1").innerText)
  {
    alert("请输入有效的验证码!");
    document.form1.yzm.value="";
    document.form1.yzm.focus();
    return false;
  }