随笔 - 3  文章 - 1  trackbacks - 0
<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

留言簿(2)

随笔档案

文章分类

文章档案

搜索

  •  

最新评论

  • 1. re: 不好的项目演示
  • 虽然项目演示失务,但我相信你的项目是最成功的,因为你的态度,你的聪明.

    You are NO.1! my lover
  • --roy117

阅读排行榜

评论排行榜

当前web应用越来越注重安全性的问题,所以再web应用项目实施中,用到了验证码的机制,其目的就是建立防刷机制,限制用户恶意提交页面,保护系统.

现在网络上各个网站上都有验证码,但是实现的形形色色各不相同.通过查资料和摸索,使用servlet来实现验证码.

一 建一个验证码生成类RandomImageGenerator ,其功能就是实现验证码

该类实现如下

import java.awt.*;
import java.awt.image.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import org.apache.commons.lang.RandomStringUtils;

/**
 * 随即图片生成器
 * 该类用于用户注册时候需要用户根据图片内容进行填写正确后方可注册
 * @author Liudong
 */
public class RandomImageGenerator {

//随即生成包含验证码的字符串   

public static String random() {
        //20060320 add by wyx
        //因为o和0,l和1很难区分,所以,去掉大小写的o和l

        String str = "";
        str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz";//初始化种子
        return RandomStringUtils.random(6, str);//返回6为的字符串
            }

    /**
     * 根据要求的数字生成图片,背景为白色,字体大小16,字体颜色黑色粗体
     * @param num 要生成的数字
     * @param out 输出流
     * @throws IOException
     */
    public static void render(String num, OutputStream out) throws IOException {
        if (num.getBytes().length > 6) {
            throw new IllegalArgumentException(
                    "The length of param num cannot exceed 6.");
        }
        //设定宽度和高度
        int width = 130; 

        int height = 30; 
        // 在内存中创建图象
        BufferedImage bi = new BufferedImage(width, height,
                                             BufferedImage.TYPE_INT_RGB);
        // 获取图形上下文
        Graphics2D g = (Graphics2D) bi.getGraphics();
        //画边框
        java.util.Random random = new java.util.Random();
        g.setColor(Color.white);
        g.fillRect(0, 0, width, height);
        //设置字体
        Font mFont = new Font("Tahoma", Font.BOLD, 16);
        g.setFont(mFont);
        g.setColor(Color.BLACK);//设置字体颜色
        //画认证码,每个认证码在不同的水平位置
        String str1[] = new String[6];
        for (int i = 0; i < str1.length; i++) {
            str1[i] = num.substring(i, i + 1);
            int w = 0;
            int x = (i + 1) % 3;

//随即生成验证码字符的水平偏移量
            if (x == random.nextInt(3)) {
                w = 19 - random.nextInt(7);
            } else {
                w = 19 + random.nextInt(7);
            }

//随即生成颜色
            Color color1 = new Color(random.nextInt(180), random.nextInt(180),
                                     random.nextInt(180));
            g.setColor(color1);
            g.drawString(str1[i], 20 * i + 10, w);
        }

        // 随机产生干扰点,并用不同的颜色表示,使图象中的认证码不易被其它程序探测到
        for (int i = 0; i < 100; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            Color color1 = new Color(random.nextInt(255), random.nextInt(255),
                                     random.nextInt(255));
            g.setColor(color1); //随即画各种颜色的点
            g.drawOval(x, y, 0, 0);
        }
        //画干扰线
        for (int i = 0; i < 5; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            Color color1 = new Color(random.nextInt(255), random.nextInt(255),
                                     random.nextInt(255));

            g.setColor(color1); //随即画各种颜色的线
            g.drawLine(x, y, x1, y1);
        }
        //图像生效
        g.dispose();
        //输出页面
        ImageIO.write(bi, "jpg", out);
    }

    public static void main(String[] args) throws IOException {
        String num = random();
        System.out.println(num);
        render(num, new FileOutputStream("D:\\test.jpg"));
        System.out.println("Image generated.");
    }
}

二 验证码的实现,使用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.HttpSession;

import peopleBlog.util.RandomImageGenerator;


/**
 * 用于产生随即图片以防止非法攻击
 * @author Liudong
 */
public class RandomImageServlet extends HttpServlet {
 public final static String RANDOM_LOGIN_KEY = "RANDOM_LOGIN_KEY";

 public void init() throws ServletException {
  System.setProperty("java.awt.headless","true");
 }

    public static String getRandomLoginKey(HttpServletRequest req) {
        return (String)req.getSession().getAttribute(RANDOM_LOGIN_KEY);
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
    {
        HttpSession ssn = req.getSession();
        if(ssn!=null) {
            String randomString = RandomImageGenerator.random();//生成种子
            ssn.setAttribute(RANDOM_LOGIN_KEY,randomString);//将种子放到session里面
            res.setContentType("image/jpeg");//设置图像生成格式

            RandomImageGenerator.render(randomString,res.getOutputStream());//输出到页面
        }
    }
}

其中 ssn.setAttribute(RANDOM_LOGIN_KEY,randomString);这一行代码的作用是:

当从页面上输入验证码,提交后,在后台sevlet或者action里面验证输入的验证码和session里面的是否一致,如果不一致返回错误信息.

三,页面实现

在web.xml文件中设置

<servlet>
    <servlet-name>image</servlet-name>
    <servlet-class>peopleBlog.RandomImageServlet</servlet-class>
    <load-on-startup>5</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>image</servlet-name>
    <url-pattern>/verifyCode.jsp</url-pattern>

  </servlet-mapping>

然后在jsp页面中

        <td><input name="verifyCode" type="text" id="verifyCode" class="input2" style="width:55px;" onkeydown="JavaScript:ifEnter()"/>&nbsp; <img src="/blog/verifyCode.jsp" align="absMiddle" border="0"/> </td>

再在目的servlet中进行验证码判断就ok了

posted on 2007-04-14 23:05 terryliu 阅读(294) 评论(0)  编辑  收藏 所属分类: java

只有注册用户登录后才能发表评论。


网站导航: