JAVAWEB项目怎么实现验证码

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVAWEB项目怎么实现验证码相关的知识,希望对你有一定的参考价值。

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import javax.imageio.ImageIO;

public class Code 
   
    // 图片的宽度。
    private int width = 160;
    // 图片的高度。
    private int height = 38;
    // 验证码字符个数
    private int codeCount = 4;
    // 验证码干扰线数
    private int lineCount = 20;
    // 验证码
    private String code = null;
    // 验证码图片Buffer
    private BufferedImage buffImg = null;
    Random random = new Random();
    
    private boolean type = false;

    public Code() 
       
    

    public Code(int width, int height) 
        this.width = width;
        this.height = height;
    

    public Code(int width, int height, int codeCount) 
        this.width = width;
        this.height = height;
        this.codeCount = codeCount;
    

    public Code(int width, int height, int codeCount, int lineCount) 
        this.width = width;
        this.height = height;
        this.codeCount = codeCount;
        this.lineCount = lineCount;
    
    
    public void init(boolean type)
       this.type = type;
    

    // 生成图片
    private void creatImage(boolean type) 
        int fontWidth = width / codeCount;// 字体的宽度
        int fontHeight = height - 5;// 字体的高度
        int codeY = height - 8;

        // 图像buffer
        buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = buffImg.getGraphics();
        //Graphics2D g = buffImg.createGraphics();
        // 设置背景色
        g.setColor(getRandColor(200, 250));
        g.fillRect(0, 0, width, height);
        
        
        
        // 设置字体
        Font font = null;
        if(!type) font = new Font("Fixedsys", Font.BOLD, fontHeight);
        else font = getFont(fontHeight);
        g.setFont(font);

        // 设置干扰线
        for (int i = 0; i < lineCount/2; i++) 
            int xs = random.nextInt(width);
            int ys = random.nextInt(height);
            int xe = xs + random.nextInt(width);
            int ye = ys + random.nextInt(height);
            g.setColor(getRandColor(1, 255));
            if(!type) g.drawLine(xs, ys, xe, ye);
            else shear(g, width, height, getRandColor(1, 255)) ;
        

        // 添加噪点
        float yawpRate = 0.01f;// 噪声率
        int area = (int) (yawpRate * width * height);
        for (int i = 0; i < area; i++) 
            int x = random.nextInt(width);
            int y = random.nextInt(height);

            buffImg.setRGB(x, y, random.nextInt(255));
        


        String str1 = randomStr(codeCount);// 得到随机字符
        this.code = str1;
        for (int i = 0; i < codeCount; i++) 
            String strRand = str1.substring(i, i + 1);
            g.setColor(getRandColor(1, 255));
            // g.drawString(a,x,y);
            // a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处
            
            g.drawString(strRand, i*fontWidth+3, codeY);
        
        

    

    // 得到随机字符
    private String randomStr(int n) 
        String str1 = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz1234567890";//I和l不要
        String str2 = "";
        int len = str1.length() - 1;
        double r;
        for (int i = 0; i < n; i++) 
            r = (Math.random()) * len;
            str2 = str2 + str1.charAt((int) r);
        
        return str2;
    

    // 得到随机颜色
    private Color getRandColor(int fc, int bc) // 给定范围获得随机颜色
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    
    
    /**
     * 产生随机字体
     */
    private Font getFont(int size) 
        Random random = new Random();
        Font font[] = new Font[5];
        font[0] = new Font("Ravie", Font.PLAIN, size);
        font[1] = new Font("Antique Olive Compact", Font.PLAIN, size);
        font[2] = new Font("Fixedsys", Font.PLAIN, size);
        font[3] = new Font("Wide Latin", Font.PLAIN, size);
        font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size);
        return font[random.nextInt(5)];
    
    
    // 扭曲方法
    private void shear(Graphics g, int w1, int h1, Color color) 
        shearX(g, w1, h1, color);
        shearY(g, w1, h1, color);
    

    private void shearX(Graphics g, int w1, int h1, Color color) 

        int period = random.nextInt(2);

        boolean borderGap = true;
        int frames = 1;
        int phase = random.nextInt(2);

        for (int i = 0; i < h1; i++) 
            double d = (double) (period >> 1)
                    * Math.sin((double) i / (double) period
                            + (6.2831853071795862D * (double) phase)
                            / (double) frames);
            g.copyArea(0, i, w1, 1, (int) d, 0);
            if (borderGap) 
                g.setColor(color);
                g.drawLine((int) d, i, 0, i);
                g.drawLine((int) d + w1, i, w1, i);
            
        

    

    private void shearY(Graphics g, int w1, int h1, Color color) 

        int period = random.nextInt(40) + 10; // 50;

        boolean borderGap = true;
        int frames = 20;
        int phase = 7;
        for (int i = 0; i < w1; i++) 
            double d = (double) (period >> 1)
                    * Math.sin((double) i / (double) period
                            + (6.2831853071795862D * (double) phase)
                            / (double) frames);
            g.copyArea(i, 0, 1, h1, 0, (int) d);
            if (borderGap) 
                g.setColor(color);
                g.drawLine(i, (int) d, i, 0);
                g.drawLine(i, (int) d + h1, i, h1);
            

        

    


    
    public void write(OutputStream sos) throws IOException 
        if(buffImg == null) creatImage(type);
        ImageIO.write(buffImg, "png", sos);
//        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(sos);
//        encoder.encode(buffImg);
        sos.close();
    

    public BufferedImage getBuffImg() 
       if(buffImg == null) creatImage(type);
        return buffImg;
    

    public String getCode() 
        return code.toLowerCase();
    
    
    //使用方法
 /*public void getCode3(HttpServletRequest req, HttpServletResponse response,HttpSession session) throws IOException
        // 设置响应的类型格式为图片格式
            response.setContentType("image/jpeg");
            //禁止图像缓存。
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
            
            
            CreateImageCode vCode = new CreateImageCode(100,30,5,10);
            session.setAttribute("code", vCode.getCode());
            vCode.write(response.getOutputStream());
            response.flushBuffer();
     */

参考技术A @RequestMapping("/service.do")
public void service(HttpServletRequest request, HttpServletResponse response,Model m)
throws ServletException, IOException
//禁止缓存
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "No-cache");
response.setDateHeader("Expires", 0);
// 指定生成的响应是图片
response.setContentType("image/jpeg");
int width = 180;
int height = 30;
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB); //创建BufferedImage类的对象
Graphics g = image.getGraphics(); //创建Graphics类的对象
Graphics2D g2d=(Graphics2D)g; //通过Graphics类的对象创建一个Graphics2D类的对象
Random random = new Random(); //实例化一个Random对象
Font mFont = new Font("华文宋体", Font.BOLD, 30); //通过Font构造字体
g.setColor(getRandColor(200, 250)); //改变图形的当前颜色为随机生成的颜色
g.fillRect(0, 0, width , height); //绘制一个填色矩形

//画一条折线
BasicStroke bs=new BasicStroke(2f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL); //创建一个供画笔选择线条粗细的对象
g2d.setStroke(bs); //改变线条的粗细
g.setColor(Color.DARK_GRAY); //设置当前颜色为预定义颜色中的深灰色
int[] xPoints=new int[3];
int[] yPoints=new int[3];
for(int j=0;j<3;j++)
xPoints[j]=random.nextInt(width - 1);
yPoints[j]=random.nextInt(height - 1);

g.drawPolyline(xPoints, yPoints,3);
//生成并输出随机的验证文字
g.setFont(mFont);
String sRand="";
int itmp=0;
for(int i=0;i<4;i++)
if(random.nextInt(2)==1)
itmp=random.nextInt(26)+65; //生成A~Z的字母
else
itmp=random.nextInt(10)+48; //生成0~9的数字

char ctmp=(char)itmp;
sRand+=String.valueOf(ctmp);
System.out.println(sRand);

Color color=new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110));
g.setColor(color);
HttpSession session=request.getSession(true);
session.setAttribute("randCheckCode",sRand);

g.drawString(String.valueOf(ctmp),30*i+40,26);
request.setAttribute("a",sRand);

g.dispose();
ImageIO.write(image,"JPEG",response.getOutputStream());
//将生成的验证码保存到Session中


//随机颜色
public Color getRandColor(int s, int e)
Random random = new Random();
if (s > 255)
s = 255;
if (e > 255)
e = 255;
int r = s + random.nextInt(e - s);
int g = s + random.nextInt(e - s);
int b = s + random.nextInt(e - s);
return new Color(r, g, b);

session中就是验证码的值!在后台调用就行
参考技术B 1、定义一个img指向后台服务
<img title="点击刷新" src="$pageContext.request.contextPath/aa/img" class="img_login_code"
onclick="this.src='$pageContext.request.contextPath/aa/img?'+Math.random();" />
2、服务
@RequestMapping(value="/img")
public void admin(HttpServletRequest request,HttpServletResponse response) throws Exception
VerifyCodeUtilsVerifyCodeUtils.outputImage("captcha_admin",null,null, request, response,verifyCode);

3、帮助类
package team.tool;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class VerifyCodeUtils

//使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符
public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
private static Random random = new Random();

/**
* 使用系统默认字符源生成验证码
* @param verifySize 验证码长度
* @return
*/
public static String generateVerifyCode(int verifySize)
return generateVerifyCode(verifySize, VERIFY_CODES);

/**
* 使用指定源生成验证码
* @param verifySize 验证码长度
* @param sources 验证码字符源
* @return
*/
public static String generateVerifyCode(int verifySize, String sources)
if(sources == null || sources.length() == 0)
sources = VERIFY_CODES;

int codesLen = sources.length();
Random rand = new Random(System.currentTimeMillis());
StringBuilder verifyCode = new StringBuilder(verifySize);
for(int i = 0; i < verifySize; i++)
verifyCode.append(sources.charAt(rand.nextInt(codesLen-1)));

return verifyCode.toString();


/**
* 生成随机验证码文件,并返回验证码值
* @param w
* @param h
* @param outputFile
* @param verifySize
* @return
* @throws IOException
*/
public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException
String verifyCode = generateVerifyCode(verifySize);
outputImage(w, h, outputFile, verifyCode);
return verifyCode;


/**
* 输出随机验证码图片流,并返回验证码值
* @param w
* @param h
* @param os
* @param verifySize
* @return
* @throws IOException
*/
public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException
String verifyCode = generateVerifyCode(verifySize);
outputImage(w, h, os, verifyCode);
return verifyCode;


/**
* 生成指定验证码图像文件
* @param w
* @param h
* @param outputFile
* @param code
* @throws IOException
*/
public static void outputImage(int w, int h, File outputFile, String code) throws IOException
if(outputFile == null)
return;

File dir = outputFile.getParentFile();
if(!dir.exists())
dir.mkdirs();

try
outputFile.createNewFile();
FileOutputStream fos = new FileOutputStream(outputFile);
outputImage(w, h, fos, code);
fos.close();
catch(IOException e)
throw e;



/**
* 输出指定验证码图片流
* @param w
* @param h
* @param os
* @param code
* @throws IOException
*/
public static void outputImage(int w, int h, OutputStream os, String code) throws IOException
int verifySize = code.length();
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Random rand = new Random();
Graphics2D g2 = image.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = new Color[5];
Color[] colorSpaces = new Color[] Color.WHITE, Color.CYAN,
Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
Color.PINK, Color.YELLOW ;
float[] fractions = new float[colors.length];
for(int i = 0; i < colors.length; i++)
colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
fractions[i] = rand.nextFloat();

Arrays.sort(fractions);

g2.setColor(Color.GRAY);// 设置边框色
g2.fillRect(0, 0, w, h);

Color c = getRandColor(200, 250);
g2.setColor(c);// 设置背景色
g2.fillRect(0, 2, w, h-4);

//绘制干扰线
Random random = new Random();
g2.setColor(getRandColor(160, 200));// 设置线条的颜色
for (int i = 0; i < 20; i++)
int x = random.nextInt(w - 1);
int y = random.nextInt(h - 1);
int xl = random.nextInt(6) + 1;
int yl = random.nextInt(12) + 1;
g2.drawLine(x, y, x + xl + 40, y + yl + 20);


// 添加噪点
float yawpRate = 0.05f;// 噪声率
int area = (int) (yawpRate * w * h);
for (int i = 0; i < area; i++)
int x = random.nextInt(w);
int y = random.nextInt(h);
int rgb = getRandomIntColor();
image.setRGB(x, y, rgb);


shear(g2, w, h, c);// 使图片扭曲

g2.setColor(getRandColor(100, 160));
int fontSize = h-4;
Font font = new Font("Algerian", Font.ITALIC, fontSize);
g2.setFont(font);
char[] chars = code.toCharArray();
for(int i = 0; i < verifySize; i++)
AffineTransform affine = new AffineTransform();
affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);
g2.setTransform(affine);
g2.drawChars(chars, i, 1, ((w-10) / verifySize) * i + 5, h/2 + fontSize/2 - 10);


g2.dispose();
ImageIO.write(image, "jpg", os);


/**
* 输出指定验证码图片流
* @param w
* @param h
* @param os
* @param code
* @throws IOException
*/
public static void outputImage(String key ,Integer w, Integer h, HttpServletRequest request, HttpServletResponse response, String code) throws IOException
int verifySize = code.length();
w = w==null?80:w;
h = h==null?30:h;
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
request.getSession().setAttribute(key, code);
Random rand = new Random();
Graphics2D g2 = image.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = new Color[5];
Color[] colorSpaces = new Color[] Color.WHITE, Color.CYAN,
Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
Color.PINK, Color.YELLOW ;
float[] fractions = new float[colors.length];
for(int i = 0; i < colors.length; i++)
colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
fractions[i] = rand.nextFloat();

Arrays.sort(fractions);

g2.setColor(Color.GRAY);// 设置边框色
g2.fillRect(0, 0, w, h);

Color c = getRandColor(200, 250);
g2.setColor(c);// 设置背景色
g2.fillRect(0, 2, w, h-4);

//绘制干扰线
Random random = new Random();
g2.setColor(getRandColor(160, 200));// 设置线条的颜色
for (int i = 0; i < 20; i++)
int x = random.nextInt(w - 1);
int y = random.nextInt(h - 1);
int xl = random.nextInt(6) + 1;
int yl = random.nextInt(12) + 1;
g2.drawLine(x, y, x + xl + 40, y + yl + 20);


// 添加噪点
float yawpRate = 0.05f;// 噪声率
int area = (int) (yawpRate * w * h);
for (int i = 0; i < area; i++)
int x = random.nextInt(w);
int y = random.nextInt(h);
int rgb = getRandomIntColor();
image.setRGB(x, y, rgb);


shear(g2, w, h, c);// 使图片扭曲

g2.setColor(getRandColor(100, 160));
int fontSize = h-4;
Font font = new Font("Algerian", Font.ITALIC, fontSize);
g2.setFont(font);
char[] chars = code.toCharArray();
for(int i = 0; i < verifySize; i++)
AffineTransform affine = new AffineTransform();
affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);
g2.setTransform(affine);
g2.drawChars(chars, i, 1, ((w-10) / verifySize) * i + 5, h/2 + fontSize/2 - 10);


g2.dispose();
// 转成JPEG格式
ServletOutputStream out = response.getOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(image);


private static Color getRandColor(int fc, int bc)
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);


private static int getRandomIntColor()
int[] rgb = getRandomRgb();
int color = 0;
for (int c : rgb)
color = color << 8;
color = color | c;

return color;


private static int[] getRandomRgb()
int[] rgb = new int[3];
for (int i = 0; i < 3; i++)
rgb[i] = random.nextInt(255);

return rgb;


private static void shear(Graphics g, int w1, int h1, Color color)
shearX(g, w1, h1, color);
shearY(g, w1, h1, color);


private static void shearX(Graphics g, int w1, int h1, Color color)

int period = random.nextInt(2);

boolean borderGap = true;
int frames = 1;
int phase = random.nextInt(2);

for (int i = 0; i < h1; i++)
double d = (double) (period >> 1)
* Math.sin((double) i / (double) period
+ (6.2831853071795862D * (double) phase)
/ (double) frames);
g.copyArea(0, i, w1, 1, (int) d, 0);
if (borderGap)
g.setColor(color);
g.drawLine((int) d, i, 0, i);
g.drawLine((int) d + w1, i, w1, i);





private static void shearY(Graphics g, int w1, int h1, Color color)

int period = random.nextInt(40) + 10; // 50;

boolean borderGap = true;
int frames = 20;
int phase = 7;
for (int i = 0; i < w1; i++)
double d = (double) (period >> 1)
* Math.sin((double) i / (double) period
+ (6.2831853071795862D * (double) phase)
/ (double) frames);
g.copyArea(i, 0, 1, h1, 0, (int) d);
if (borderGap)
g.setColor(color);
g.drawLine(i, (int) d, i, 0);
g.drawLine(i, (int) d + h1, i, h1);





public static void main(String[] args) throws IOException
File dir = new File("F:/verifies");
int w = 200, h = 80;
for(int i = 0; i < 50; i++)
String verifyCode = generateVerifyCode(4);
File file = new File(dir, verifyCode + ".jpg");
outputImage(w, h, file, verifyCode);


JAVAWEB项目实现验证码中文英文数字组合

验证码基础

一.什么是验证码及它的作用

   验证码为全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计算机的公共全自动程序,这个问题可以由计算机生成并评判,但是必须只有人类才能解答.可以防止恶意破解密码、刷票、论坛灌水、有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登录。

 

二.图文验证码的原理

   在servlet中随机生成一个指定位置的验证码,一般为四位,然后把该验证码保存到session中.在通过Java的绘图类以图片的形式输出该验证码。为了增加验证码的安全级别,可以输出图片的同时输出干扰线,最后在用户提交数据的时候,在服务器端将用户提交的验证码和Session保存的验证码进行比较。

 

三.验证码所需的技术

    :i.因为验证码中的文字,数字,应为都是可变的,故要用到随机生成数技术。

       ii.如果验证码中包含汉字,则要用到汉字生成技术.

       iii.可以使用Ajax技术实现局部刷新

       iv.可以使用图片的缩放和旋转技术,

       vi.随机绘制干扰线(可以是折现,直线等)

       vii.如果考虑到验证码的安全性,可以使用MD5加密.

中文、英文、数字组合验证码:

package randCodeImage.servlet;

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;

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 javax.imageio.ImageIO;
/**
 * 随机生成英文、数字、中文验证图片
 * 
 * @author wkr
 * 
 */
public class PictureCheckCode extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public PictureCheckCode() {
        super();
    }

    public void destroy() {
        super.destroy(); 
    }

    public void init() throws ServletException {
        super.init();
    }
    /*该方法主要作用是获得随机生成的颜色*/ 
    public Color getRandColor(int s,int e){
        Random random=new Random ();
        if(s>255) s=255;
        if(e>255) e=255;
        int r,g,b;
        r=s+random.nextInt(e-s);    //随机生成RGB颜色中的r值
        g=s+random.nextInt(e-s);    //随机生成RGB颜色中的g值
        b=s+random.nextInt(e-s);    //随机生成RGB颜色中的b值
        return new Color(r,g,b);
    }

    @Override
    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //设置不缓存图片
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "No-cache");
        response.setDateHeader("Expires", 0);
//        request.setCharacterEncoding("UTF-8");
//        request.setCharacterEncoding("UTF-8");
//        response.setContentType("text/html;charset=UTF-8");
        //指定生成的响应图片,一定不能缺少这句话,否则错误.
        response.setContentType("image/jpeg");
        int width=86,height=32;        //指定生成验证码的宽度和高度
        BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);    //创建BufferedImage对象,其作用相当于一图片
        Graphics g=image.getGraphics();        //创建Graphics对象,其作用相当于画笔
        Graphics2D g2d=(Graphics2D)g;        //创建Grapchics2D对象
        Random random=new Random();
        Font mfont=new Font("楷体",Font.BOLD,24);    //定义字体样式
        g.setColor(getRandColor(200,250));
        g.fillRect(0, 0, width, height);    //绘制背景
        g.setFont(mfont);                    //设置字体
        g.setColor(getRandColor(180,200));
        
        //绘制100条颜色和位置全部为随机产生的线条,该线条为2f
        for(int i=0;i<100;i++){
            int x=random.nextInt(width-1);
            int y=random.nextInt(height-1);
            int x1=random.nextInt(6)+1;
            int y1=random.nextInt(12)+1;
            BasicStroke bs=new BasicStroke(2f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL);    //定制线条样式
            Line2D line=new Line2D.Double(x,y,x+x1,y+y1);
            g2d.setStroke(bs);
            g2d.draw(line);        //绘制直线
        }
        //输出由英文,数字,和中文随机组成的验证文字,具体的组合方式根据生成随机数确定。
        String sRand="";
        String ctmp="";
        int itmp=0;
        //制定输出的验证码为四位
        for(int i=0;i<4;i++){
            switch(random.nextInt(3)){
                case 1:        //生成A-Z的字母
                     itmp=random.nextInt(26)+65;
                     ctmp=String.valueOf((char)itmp);
                     break;
                case 2:        //生成汉字
                     String[] rBase={"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"}; 
                     //生成第一位区码
                     int r1=random.nextInt(3)+11;
                     String str_r1=rBase[r1];
                     //生成第二位区码
                     int r2;
                     if(r1==13){
                         r2=random.nextInt(7);     
                     }else{
                         r2=random.nextInt(16);
                     }
                     String str_r2=rBase[r2];
                     //生成第一位位码
                     int r3=random.nextInt(6)+10;
                     String str_r3=rBase[r3];
                     //生成第二位位码
                     int r4;
                     if(r3==10){
                         r4=random.nextInt(15)+1;
                     }else if(r3==15){
                         r4=random.nextInt(15);
                     }else{
                         r4=random.nextInt(16);
                     }
                     String str_r4=rBase[r4];
                     //将生成的机内码转换为汉字
                     byte[] bytes=new byte[2];
                     //将生成的区码保存到字节数组的第一个元素中
                     String str_12=str_r1+str_r2;
                     int tempLow=Integer.parseInt(str_12, 16);
                     bytes[0]=(byte) tempLow;
                     //将生成的位码保存到字节数组的第二个元素中
                     String str_34=str_r3+str_r4;
                     int tempHigh=Integer.parseInt(str_34, 16);
                     bytes[1]=(byte)tempHigh;
                     ctmp=new String(bytes,"GB2312");
                     break;
                default:
                     itmp=random.nextInt(10)+48;
                     ctmp=String.valueOf((char)itmp);
                     break;
            }
            sRand+=ctmp;
            Color color=new Color(20+random.nextInt(110),20+random.nextInt(110),random.nextInt(110));
            g.setColor(color);
            //将生成的随机数进行随机缩放并旋转制定角度 PS.建议不要对文字进行缩放与旋转,因为这样图片可能不正常显示
            /*将文字旋转制定角度*/
            Graphics2D g2d_word=(Graphics2D)g;
            AffineTransform trans=new AffineTransform();
            trans.rotate((45)*3.14/180,15*i+8,7);
            /*缩放文字*/
            float scaleSize=random.nextFloat()+0.8f;
            if(scaleSize>1f) scaleSize=1f;
            trans.scale(scaleSize, scaleSize);
            g2d_word.setTransform(trans);
            g.drawString(ctmp, 15*i+18, 14);
        }
        System.out.println("验证码:>>>"+sRand);
        HttpSession session=request.getSession(true);
        session.setAttribute("randCheckCode", sRand);
        g.dispose();    //释放g所占用的系统资源
        ImageIO.write(image,"JPEG",response.getOutputStream());    //输出图片
    }
}

英文、数字组合验证码(附加读取配置文件):

package randCodeImage.servlet;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import randCodeImage.util.ResourceUtil;

//import com.sun.image.codec.jpeg.JPEGCodec;
//import com.sun.image.codec.jpeg.JPEGEncodeParam;
//import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**
 * 随机生成英文、数字验证图片
 * 
 * @author wkr
 * 
 */
public class RandCodeImageServlet extends HttpServlet {
    private static final long serialVersionUID = -1257947018545327308L;
    private static final String SESSION_KEY_OF_RAND_CODE = "randCode"; // todo 要统一常量
    /**
     * 
     */
    private static final int count = 200;

    /**
     * 定义图形大小
     */
    private static final int width = 105;
    /**
     * 定义图形大小
     */
    private static final int height = 35;
    // private Font mFont = new Font("Arial Black", Font.PLAIN, 15); //设置字体
    /**
     * 干扰线的长度=1.414*lineWidth
     */
    private static final int lineWidth = 2;

    @Override
    public void doGet(final HttpServletRequest request,
            final HttpServletResponse response) throws ServletException,
            IOException {
        // 设置页面不缓存
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        // response.setContentType("image/png");

        // 在内存中创建图象
        final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取图形上下文
        final Graphics2D graphics = (Graphics2D) image.getGraphics();

        // 设定背景颜色
        graphics.setColor(Color.WHITE); // ---1
        graphics.fillRect(0, 0, width, height);
        // 设定边框颜色
//        graphics.setColor(getRandColor(100, 200)); // ---2
        graphics.drawRect(0, 0, width - 1, height - 1);

        final Random random = new Random();
        // 随机产生干扰线,使图象中的认证码不易被其它程序探测到
        for (int i = 0; i < count; i++) {
            graphics.setColor(getRandColor(150, 200)); // ---3

            final int x = random.nextInt(width - lineWidth - 1) + 1; // 保证画在边框之内
            final int y = random.nextInt(height - lineWidth - 1) + 1;
            final int xl = random.nextInt(lineWidth);
            final int yl = random.nextInt(lineWidth);
            graphics.drawLine(x, y, x + xl, y + yl);
        }

        // 取随机产生的认证码(4位数字)
        final String resultCode = exctractRandCode();
        for (int i = 0; i < resultCode.length(); i++) {
            // 将认证码显示到图象中,调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
            // graphics.setColor(new Color(20 + random.nextInt(130), 20 + random
            // .nextInt(130), 20 + random.nextInt(130)));

            // 设置字体颜色
            graphics.setColor(Color.BLACK);
            // 设置字体样式
//            graphics.setFont(new Font("Arial Black", Font.ITALIC, 18));
            graphics.setFont(new Font("Times New Roman", Font.BOLD, 24));
            // 设置字符,字符间距,上边距
            graphics.drawString(String.valueOf(resultCode.charAt(i)), (23 * i) + 8, 26);
        }

        // 将认证码存入SESSION
        request.getSession().setAttribute(SESSION_KEY_OF_RAND_CODE, resultCode);
        // 图象生效
        graphics.dispose();

        // 输出图象到页面
        ImageIO.write(image, "JPEG", response.getOutputStream());
    }

    @Override
    public void doPost(final HttpServletRequest request,
            final HttpServletResponse response) throws ServletException,
            IOException {
        doGet(request, response);
    }

    /**
     * @return 随机码
     */
    private String exctractRandCode() {
        final String randCodeType = ResourceUtil.getRandCodeType();
        int randCodeLength = Integer.parseInt(ResourceUtil.getRandCodeLength());
        if (randCodeType == null) {
            return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);
        } else {
            switch (randCodeType.charAt(0)) {
            case \'1\':
                return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);
            case \'2\':
                return RandCodeImageEnum.LOWER_CHAR.generateStr(randCodeLength);
            case \'3\':
                return RandCodeImageEnum.UPPER_CHAR.generateStr(randCodeLength);
            case \'4\':
                return RandCodeImageEnum.LETTER_CHAR.generateStr(randCodeLength);
            case \'5\':
                return RandCodeImageEnum.ALL_CHAR.generateStr(randCodeLength);

            default:
                return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);
            }
        }
    }

    /**
     * 描述:
     * 
     * @param fc
     *            描述:
     * @param bc
     *            描述:
     * 
     * @return 描述:
     */
    private Color getRandColor(int fc, int bc) { // 取得给定范围随机颜色
        final Random random = new Random();
        if (fc > 255) {
            fc = 255;
        }
        if (bc > 255) {
            bc = 255;
        }

        final int r = fc + random.nextInt(bc - fc);
        final int g = fc + random.nextInt(bc - fc);
        final int b = fc + random.nextInt(bc - fc);

        return new Color(r, g, b);
    }
}

/**
 * 验证码辅助类
 * 
 * @author 张国明 guomingzhang2008@gmail.com <br/>
 *         2012-2-28 下午2:15:14
 * 
 */
enum RandCodeImageEnum {
    /**
     * 混合字符串
     */
    ALL_CHAR("123456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"),
    /**
     * 字符
     */
    LETTER_CHAR("abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"),
    /**
     * 小写字母
     */
    LOWER_CHAR("abcdefghjkmnpqrstuvwxyz"),
    /**
     * 数字
     */
    NUMBER_CHAR("123456789"),
    /**
     * 大写字符
     */
    UPPER_CHAR("ABCDEFGHJKMNPQRSTUVWXYZ");
    /**
     * 待生成的字符串
     */
    private String charStr;

    /**
     * @param charStr
     */
    private RandCodeImageEnum(final String charStr) {
        this.charStr = charStr;
    }

    /**
     * 生产随机验证码
     * 
     * @param codeLength
     *            验证码的长度
     * @return 验证码
     */
    public String generateStr(final int codeLength) {
        final StringBuffer sb = new StringBuffer();
        final Random random = new Random();
        final String sourseStr = getCharStr();

        for (int i = 0; i < codeLength; i++) {
            sb.append(sourseStr.charAt(random.nextInt(sourseStr.length())));
        }

        return sb.toString();
    }

    /**
     * @return the {@link #charStr}
     */
    public String getCharStr() {
        return charStr;
    }

}

读取配置文件工具类:

package randCodeImage.util;

import java.util.ResourceBundle;
//commons-lang-2.6.jar
import org.apache.commons.lang.StringUtils;

/** 
 * 项目参数工具类
 * @author otowa
 *
 */
public class ResourceUtil {

    //获得指定的环境变量的值env若获取不到,由默认值pro代替
    private static final String env = StringUtils.defaultIfBlank(System.getProperty("env"), StringUtils.defaultIfBlank(System.getenv("env"), "pro"));
    
    private static final ResourceBundle sysConfig = java.util.ResourceBundle.getBundle(env+"/sysConfig");
    
    /**
     * 获取随机码的长度
     *
     * @return 随机码的长度
     */
    public static String getRandCodeLength() {
        return sysConfig.getString("randCodeLength");
    }
    /**
     * 获取随机码的类型
     *
     * @return 随机码的类型
     */
    public static String getRandCodeType() {
        return sysConfig.getString("randCodeType");
    }
}

sysConfig.properties配置文件(路径:/resources/dev/sysConfig.properties):

#随机码的长度
randCodeLength=4
#随机码的类型
randCodeType=5

验证码jsp页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

    /**
     * 异步刷新验证码
     */
    $(\'#randCodeImage\').click(function(){
        reloadRandCodeImage();
    });
    function reloadRandCodeImage() {
        var date = new Date();
        var img = document.getElementById("randCodeImage");
        img.src=\'randCodeImageServlet?a=\' + date.getTime();
    }
</script>
<script language="javascript">
    /**
     * 异步刷新验证码
     */
    function myReload() {  
        document.getElementById("CreateCheckCode").src = document  
                .getElementById("CreateCheckCode").src  
                + "?nocache=" + new Date().getTime();  
    }  
</script>  
</head>
<body>
    <form action="">
        英文、数字验证码:
        <input type="text" name="code" size="4" >
        <img id="randCodeImage" alt="验证码" src="randCodeImageServlet">
        <a id="verifyChange" href="javascript:void(0);" onclick="reloadRandCodeImage();" >换一张</a>
    </form>
    
    <form action="page/randCodeImage/Check.jsp" method="post">
        中文、英文、数字验证码:
        <input name="checkCode" type="text" id="checkCode" title="验证码区分大小写"  
            size="8" maxlength="4" />  
        <img src="PictureCheckCode" id="CreateCheckCode" align="middle">  
        <a href="javascript:;" onclick="myReload()"> 看不清,换一个</a>  
        <input type="submit" value="提交" />  
    </form>  
</body>
</html>

提交效验jsp页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page language="javaJAVAWEB项目实现验证码中文英文数字组合

javaweb中如何实时判定验证码的正误

JavaWeb网上图书商城完整项目--day02-12.激活功能各层实现

Javaweb 响应——生成验证码

Javaweb 响应——生成验证码

JavaWeb使用Kaptcha生成验证码(jar版)