java生成验证码

来源:互联网 发布:list转json字符串 编辑:程序博客网 时间:2024/04/26 12:53

论坛中的验证码的作用

因为你的WEB站有时会碰到客户机恶意攻击,其中一种很常见的攻击手段就是 身份欺骗_它通过

 

在客户端脚本写入一些代码,然后利用其,客户机在网站,论坛反复登陆,或者攻击者创建一个HTML窗体,其窗体如果包含了你注册窗体或发帖窗体等相同的字段,然后利用"http-post"传输数据到服务器,服务器会

 

执行相应的创建帐户,提交垃圾数据等操作,如果服务器本身不能有效验证并拒绝此非法操作,它会很严重耗费

 

其系统资源,降低网站性能甚至使程序崩溃.

 

而现在流行的判断访问WEB程序是合法用户还是恶意操作的方式,就是采用 一种叫 "字符校验"的技术.

 

WEB网站像现在的动网论坛,他采用达到方法是为客户提供一个包含随即字符串的图片,用户必须读取

 

这些字符串,然后随 登陆窗体或者发帖窗体等用户创建的窗体一起提交.

 

因为人的话,可以很容易读出图片中的数字,但如果是一段客户端攻击代码,通过一般手段是很难识别验证码的

 

这样可以确保当前访问是来自一个人而非机器.

验证码:就是将一串随机产生的数字或符号,生成一幅图片, 图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能。

作用:

验证码一般是防止有人利用机器人自动批量注册、对特定的注册用户用特定程序暴力破解方式进行不断的登陆、灌水。因为验证码是一个混合了数字或符号的图片,人眼看起来都费劲,机器识别起来就更困难。像百度贴吧未登录发贴要输入验证码大概是防止大规模匿名回帖的发生。

 

 

一般注册用户ID的地方以及各大论坛都要要输入验证码

 

常见的验证码

1>四位数字,随机的一数字字符串,最原始的验证码,验证作用几乎为零。

2>CSDN网站用户登录用的是GIF格式,目前常用的随机数字图片验证码。图片上的字符比较中规中矩,验证作用比上一个好。没有基本图形图像学知识的人,不可破!可惜读取它的程序,在CSDN使用它的第一天,好像就在论坛里发布了,真是可怜!

3>QQ网站用户登录用的是PNG格式,图片用的随机数字+随机大写英文字母,整个构图有点张扬,每刷新一次,每个字符还会变位置呢!有时候出来的图片,人眼都识别不了,厉害啊…

4>MS的hotmail申请时候的是BMP格式, 随机数字+随机大写英文字母+随机干扰像素+随机位置。

5>Google的Gmail注册时候的是JPG格式,随机英文字母+随机颜色+随机位置+随机长度。

6>其他各大论坛的是XBM格式,内容随机。

验证码的作用:有效防止这种问题对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上是用验证码是现在很多网站通行的方式(比 如招商银行的网上个人银行,腾讯的QQ社区),我们利用比较简易的方式实现了这个功能。虽然登陆麻烦一点,但是对社区还来说这个功能还是很有必要,也很重 要。但我们还是提醒大家主要保护自己的密码,尽量使用混杂了数字、字母、符号在内的6位以上密码,不要使用诸如1234之类的简单密码或者与用户名相同、 类似的密码。 不要因为只是来iclub问问问题,就随意设置密码,保护你自己的密码也是保护你自己,免得你的账号给人盗用给自己带来不必要的麻烦。 ~

(1).验证码一般是防止批量注册的,人眼看起来都费劲,何况是机器。二像百度贴吧未登录发贴要输入验证码大概是防止大规模匿名回帖的发生目 前,不少网站为了防止用户利用机器人自动注册、登录、灌水,都采用了验证码技术。所谓验证码,就是将一串随机产生的数字或符号,生成一幅图片, 图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能。

(2).一般注册用户ID的地方以及各大论坛都要要输入验证码

(3).常见的验证码

1,四位数字,随机的一数字字符串,最原始的验证码,验证作用几乎为零。2,CSDN网站用户登录用的是GIF格式,目前常用的随机数字图片验证 码。图片上的字符比较中规中矩,验证作用比上一个好。没有基本图形图像学知识的人,不可破!可惜读取它的程序,在CSDN使用它的第一天,好像就在论坛里 发布了,真是可怜!

3,QQ网站用户登录用的是PNG格式,图片用的随机数字+随机大写英文字母,整个构图有点张扬,每刷新一次,每个字符还会变位置呢!有时候 出来的图片,人眼都识别不了,厉害啊…4,MS的hotmail申请时候的是BMP格式, 随机数字+随机大写英文字母+随机干扰像素+随机位置。

5,Google的Gmail注册时候的是JPG格式,随机英文字母+随机颜色+随机位置+随机长度。6,其他各大论坛的是XBM格式,内容随机。

(4)意义:不少网站为了防止用户利用机器人自动注册、登录、灌水,都采用了验证码技术。所谓验证码,就是将一串随机产生的数字或符号,生成一幅 图片,图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能。

验证码的作用:有效防止这种问题对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上是用验证码是现在很多网站通行的方式 (比如招商银行的网上个人银行,腾讯的QQ社区),我们利用比较简易的方式实现了这个功能。虽然登陆麻烦一点,但是对社区还来说这个功能还是很有必要,也 很重要。但我们还是提醒大家主要保护自己的密码,尽量使用混杂了数字、字母、符号在内的6位以上密码,不要使用诸如1234之类的简单密码或者与用户名相 同、类似的密码。 不要因为只是来iclub问问问题,就随意设置密码,保护你自己的密码也是保护你自己,免得你的账号给人盗用给自己带来不必要的麻烦。

 

 

 

 

 

实现的思路:

首先,需要创建一个Servlet。该Servlet通过字节型响应给客户端返回一个图片,该图片是通过JDK中Java 2D的类库来生成一个图片。图片的生成是依靠一个随机数来完成,然后将这个随机数写成图片格式。最后在Session将这个随机的字符串的状态保持住,以便在用户填写后进行对比。

其次,在需要加入验证码的JSP页面中,通过<img src="生成验证码图片的URI"/>引入该图片。

最后,单用户填写完验证码后,提交到某一个Servlet中。在这个Servlet中,通过request.getParameter()方法获取用户添加的验证码,然后取出后与Session中生成的验证码进行对比,如果对比成功就表示通过,否则返回该页面给用户提示验证码错误的信息。

参考代码:

1、用来生成验证码图片的Servlet:

package com.bluedot.common;

 

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics2D;

import java.awt.image.BufferedImage;

import java.util.Random;

 

import javax.imageio.ImageIO;

import javax.servlet.ServletException;

import javax.servlet.ServletOutputStream;

import javax.servlet.http.HttpServlet;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

 

public class ValidateCodeServlet extendsHttpServlet {

 

       //验证码图片的宽度。

       privateint width = 60;

       // 验证码图片的高度。

       privateint height = 20;

       // 验证码字符个数

       privateint codeCount = 4;

 

       privateint x = 0;

       // 字体高度

       privateint fontHeight;

       privateint codeY;

 

       char[]codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',

                     'K','L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',

                     'X','Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

 

       /**

        * 初始化验证图片属性

        */

       publicvoid init() throws ServletException {

              //从web.xml中获取初始信息

              //宽度

              StringstrWidth = this.getInitParameter("width");

              //高度

              StringstrHeight = this.getInitParameter("height");

              //字符个数

              StringstrCodeCount = this.getInitParameter("codeCount");

 

              //将配置的信息转换成数值

              try{

                     if(strWidth != null && strWidth.length() != 0) {

                            width= Integer.parseInt(strWidth);

                     }

                     if(strHeight != null && strHeight.length() != 0) {

                            height= Integer.parseInt(strHeight);

                     }

                     if(strCodeCount != null && strCodeCount.length() != 0) {

                            codeCount= Integer.parseInt(strCodeCount);

                     }

              }catch (NumberFormatException e) {

              }

 

              x= width / (codeCount + 1);

              fontHeight= height - 2;

              codeY= height - 4;

 

       }

 

       protectedvoid service(HttpServletRequest req, HttpServletResponse resp)

                     throwsServletException, java.io.IOException {

 

              //定义图像buffer

              BufferedImagebuffImg = new BufferedImage(width, height,

                            BufferedImage.TYPE_INT_RGB);

              Graphics2Dg = buffImg.createGraphics();

 

              //创建一个随机数生成器类

              Randomrandom = new Random();

 

              //将图像填充为白色

              g.setColor(Color.WHITE);

              g.fillRect(0,0, width, height);

 

              //创建字体,字体的大小应该根据图片的高度来定。

              Fontfont = new Font("Fixedsys",Font.PLAIN, fontHeight);

              //设置字体。

              g.setFont(font);

 

              //画边框。

              g.setColor(Color.BLACK);

              g.drawRect(0,0, width - 1, height - 1);

 

              //随机产生160条干扰线,使图象中的认证码不易被其它程序探测到。

              g.setColor(Color.BLACK);

              for(int i = 0; i < 160; i++) {

                     intx = random.nextInt(width);

                     inty = random.nextInt(height);

                     intxl = random.nextInt(12);

                     intyl = random.nextInt(12);

                     g.drawLine(x,y, x + xl, y + yl);

              }

 

              //randomCode用于保存随机产生的验证码,以便用户登录后进行验证。

              StringBufferrandomCode = new StringBuffer();

              intred = 0, green = 0, blue = 0;

 

              //随机产生codeCount数字的验证码。

              for(int i = 0; i < codeCount; i++) {

                     //得到随机产生的验证码数字。

                     StringstrRand = String.valueOf(codeSequence[random.nextInt(36)]);

                     //产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同。

                     red= random.nextInt(255);

                     green= random.nextInt(255);

                     blue= random.nextInt(255);

 

                     //用随机产生的颜色将验证码绘制到图像中。

                     g.setColor(newColor(red, green, blue));

                     g.drawString(strRand,(i + 1) * x, codeY);

 

                     //将产生的四个随机数组合在一起。

                     randomCode.append(strRand);

              }

              //将四位数字的验证码保存到Session中。

              HttpSessionsession = req.getSession();

              session

                            .setAttribute(Constants.VALIDATE_CODE_KEY,randomCode

                                          .toString());

 

              //禁止图像缓存。

              resp.setHeader("Pragma","no-cache");

              resp.setHeader("Cache-Control","no-cache");

              resp.setDateHeader("Expires",0);

 

              resp.setContentType("image/jpeg");

 

              //将图像输出到Servlet输出流中。

              ServletOutputStreamsos = resp.getOutputStream();

              ImageIO.write(buffImg,"jpeg", sos);

              sos.close();

       }

}

2、使用动态图片验证码的JSP页面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%

    String path = request.getContextPath();

    String basePath = request.getScheme() + "://"

           + request.getServerName() + ":" + request.getServerPort()

           + path + "/";

%>

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN">

<html>

    <head>

       <base href="<%=basePath%>">

 

       <title>My JSP 'index.jsp' starting page</title>

       <meta http-equiv="pragma" content="no-cache">

       <meta http-equiv="cache-control" content="no-cache">

       <meta http-equiv="expires" content="0">

       <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

       <meta http-equiv="description" content="This is mypage">

       <!--

    <link rel="stylesheet" type="text/css"href="styles.css">

    -->

    </head>

 

    <body>

       <%

           String msg = (String)request.getAttribute("msg");

           if(msg != null && msg.length()>0)

           {

       %>

       <font color="red"><%=msg %></font>

       <%

           }

       %>

       <form action="Login.do" method="post">

           <table align="center">

              <tr height="40">

                  <td>

                     User:

                  </td>

                  <td>

                     <input type="text" name="userName" />

                  </td>

              </tr>

              <tr height="40">

                  <td>

                     Pwd:

                  </td>

                  <td>

                     <input type="password" name="userPWD" />

                  </td>

              </tr>

              <tr>

                  <td>

                     Code:

                  </td>

                  <td>

                     <input type="text" name="validateCode" maxlength="4" size="6"/>

                     <img src="ValidateCodeServlet.do" />

                  </td>

              </tr>

              <tr>

                  <td colspan="2" align="center">

                     <input type="submit" />

                  </td>

              </tr>

           </table>

       </form>

    </body>

</html>

3、用来处理用户提交的Servlet:

package com.bluedot.web.servlet;

 

import java.io.IOException;

 

importjavax.servlet.ServletException;

importjavax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

 

importcom.bluedot.common.Constants;

 

public class Login extends HttpServlet {

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

           throws ServletException,IOException {

 

       request.setCharacterEncoding("utf-8");

       String userName = request.getParameter("userName");

       String userPwd = request.getParameter("userPWD");

       String validateCode = request.getParameter("validateCode");

 

       String validateCodeInSession = (String) request.getSession()

              .getAttribute(Constants.VALIDATE_CODE_KEY);

 

       if (validateCodeInSession == null || validateCode ==null

              ||!validateCode.equalsIgnoreCase(validateCodeInSession)) {

           request.setAttribute("msg", "验证码错误");

           request.getSession().removeAttribute(Constants.VALIDATE_CODE_KEY);

           request.getRequestDispatcher("index.jsp")

                  .forward(request, response);

       } else {

           // 调用后台业务层的方法进行用户名和密码的校验,在这里直接进行假校验!

           if ("admin".equals(userName)&& "admin".equals(userPwd)) {

              request.getSession().removeAttribute(

                     Constants.VALIDATE_CODE_KEY);

              response.sendRedirect("ok.jsp");

           } else {

              request.getSession().removeAttribute(

                     Constants.VALIDATE_CODE_KEY);

              request.setAttribute("msg", "用户名或者密码错误");

              request.getRequestDispatcher("index.jsp").forward(request,

                     response);

           }

       }

    }

 

}