posts - 0, comments - 77, trackbacks - 0, articles - 356
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

随机数字验证码的生成

Posted on 2007-09-27 14:29 semovy 阅读(545) 评论(0)  编辑  收藏 所属分类: ServletJ2EE综合

有时候在我们的网络应用中,防止程序自动登录搞破坏,我们一般都会加上验证码,这些验证码一般来说都是由人来识别的,当然,如果验证码很有规律,或者说很清楚,漂亮,那么也是可能被程序识别的,我以前就识别过某网站的验证码,因为比较有规律,所以被识别了,并且识别率达到99%左右,其实我们可以制作很复杂一点的验证码,添加一些干扰的线条或者字体变形,使程序识别的难度加大,这样,我们的目的也就达到了.

下面是生成的图片:


代码如下,JSP代码

<%@page contentType="image/jpeg"%>
<%@page pageEncoding="UTF-8"%>
<%@ page import="java.awt.*,javax.imageio.*,java.io.*,java.util.*,java.awt.image.*" %>
<%--
The taglib directive below imports the JSTL library. If you uncomment it,
you must also add the JSTL library to the project. The Add Library action
on Libraries node in Projects view can be used to add the JSTL 
1.1 library.
--%>
<%--
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 
--%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%!String s="";%>
<%
java.util.List
<String> fonts=new ArrayList<String>();
GraphicsEnvironment.getLocalGraphicsEnvironment().preferLocaleFonts();
String[] names
=GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(Locale.CHINA);
for(String s:names){
    
char c=s.charAt(0);
    
if(Character.isLowerCase(c)||Character.isUpperCase(c)){
        
    }
else{
        fonts.add(s);
    }
}
BufferedImage bi
=new BufferedImage(200,50,BufferedImage.TYPE_INT_RGB);
Graphics2D g
=bi.createGraphics();
char[] cs={'0','1','2','3','4','5','6','7','8','9'};
char[] use=new char[4];
g.setColor(
new Color(240,240,240));
g.fillRect(
0,0,200,50);
for(int i=0;i<4;i++){
    Point p
=new Point(5+(i*((int)(Math.random()*10)+40)),40);
    
int size=0;
    
int[] sizes=new int[20];
    
for(int j=0;j<20;j++){
        sizes[j]
=30+j;
    }
    size
=sizes[(int)(Math.random()*sizes.length)];
    
int face=0;
    
if(Math.random()*10>5){
        face
=Font.BOLD;
    }
else{
        face
=Font.ITALIC;
    }
    use[i]
=cs[(int)(Math.random()*cs.length)];
    g.setPaint(
new GradientPaint(p.x,p.y,new Color((int)(Math.random()*256),0,(int)(Math.random()*256)),
            p.x,p.y
-size,new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256))));
    g.setFont(
new Font(fonts.get((int)(Math.random()*fonts.size())),face,size));
    g.drawString(
""+use[i],p.x,p.y);
}
s
=new String(use);
session.setAttribute(
"code", s);
g.setPaint(
null);
for(int i=0;i<4;i++){
    g.setColor(
new Color((int)(Math.random()*0x00FFFFFFF)));
    g.drawLine((
int)(Math.random()*200),(int)(Math.random()*50),(int)(Math.random()*200),(int)(Math.random()*50));
}
Random random 
= new Random();
for (int i=0;i<88;i++) {
    
int x = random.nextInt(200);
    
int y = random.nextInt(50);
    g.setColor(
new Color((int)(Math.random()*0x00FFFFFFF)));
    g.setStroke(
new BasicStroke((float)(Math.random()*3)));
    g.drawLine(x,y,x,y);
}
OutputStream ot
=response.getOutputStream();
ImageIO.write(bi,
"JPEG",ot);
g.dispose();
ot.close();
%>

以下是Servlet代码
/*
 * Code.java
 *
 * Created on 2007年9月21日, 下午12:08
 
*/

package com.hadeslee;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import javax.imageio.ImageIO;

import javax.servlet.*;
import javax.servlet.http.*;

/**
 *
 * 
@author lbf
 * 
@version
 
*/
public class Code extends HttpServlet {
    
    
/** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * 
@param request servlet request
     * 
@param response servlet response
     
*/
    
private List<String> fonts=new ArrayList<String>();
    
public Code(){
        initFonts();
    }
    
private void initFonts(){
        GraphicsEnvironment.getLocalGraphicsEnvironment().preferLocaleFonts();
        String[] names
=GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(Locale.CHINA);
        
for(String s:names){
            
char c=s.charAt(0);
            
if(Character.isLowerCase(c)||Character.isUpperCase(c)){
                
            }
else{
                fonts.add(s);
            }
        }
    }
    
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    
throws ServletException, IOException {
        response.setContentType(
"image/jpeg;charset=UTF-8");
        OutputStream out
=response.getOutputStream();
        BufferedImage bi
=new BufferedImage(200,50,BufferedImage.TYPE_INT_RGB);
        Graphics2D g
=bi.createGraphics();
        
char[] cs={'0','1','2','3','4','5','6','7','8','9'};
        
char[] use=new char[4];
        g.setColor(
new Color(240,240,240));
        g.fillRect(
0,0,200,50);
        
for(int i=0;i<4;i++){
            Point p
=getPoint(i);
            
int size=getSize();
            use[i]
=cs[(int)(Math.random()*cs.length)];
           
// g.setColor(new Color((int)(Math.random()*256),0,(int)(Math.random()*256)));
            g.setPaint(getPaint(p,size));
            g.setFont(
new Font(fonts.get((int)(Math.random()*fonts.size())),getFace(),size));
            g.drawString(
""+use[i],p.x,p.y);
        }
        g.setStroke(
new BasicStroke(1.0f));
        g.setPaint(
null);
        
for(int i=0;i<4;i++){
            g.setColor(
new Color((int)(Math.random()*0x00FFFFFFF)));
            g.drawLine((
int)(Math.random()*200),(int)(Math.random()*50),(int)(Math.random()*200),(int)(Math.random()*50));
        }
        Random random 
= new Random();
        
for (int i=0;i<88;i++) {
            
int x = random.nextInt(200);
            
int y = random.nextInt(50);
            g.setColor(
new Color((int)(Math.random()*0x00FFFFFFF)));
            g.setStroke(getStroke());
            g.drawLine(x,y,x,y);
        }
        ImageIO.write(bi,
"JPEG",out);
        out.close();
        g.dispose();
    }
    
private Stroke getStroke(){
      BasicStroke bs
=new BasicStroke((float)(Math.random()*3));
      
return bs;
    }
    
private Point getPoint(int index){
        
return new Point(5+(index*((int)(Math.random()*10)+40)),40);
    }
    
private Paint getPaint(Point p,int size){
        GradientPaint gp
=new GradientPaint(p.x,p.y,new Color((int)(Math.random()*256),0,(int)(Math.random()*256)),
                p.x,p.y
-size,new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256)));
        
return gp;
    }
    
private int getFace(){
        
if(Math.random()*10>5){
            
return Font.BOLD;
        }
else{
            
return Font.ITALIC;
        }
    }
    
private int getSize(){
        
int[] sizes=new int[20];
        
for(int i=0;i<20;i++){
            sizes[i]
=30+i;
        }
        
return sizes[(int)(Math.random()*sizes.length)];
    }
    
    
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** Handles the HTTP <code>GET</code> method.
     * 
@param request servlet request
     * 
@param response servlet response
     
*/
    
protected void doGet(HttpServletRequest request, HttpServletResponse response)
    
throws ServletException, IOException {
        processRequest(request, response);
    }
    
    
/** Handles the HTTP <code>POST</code> method.
     * 
@param request servlet request
     * 
@param response servlet response
     
*/
    
protected void doPost(HttpServletRequest request, HttpServletResponse response)
    
throws ServletException, IOException {
        processRequest(request, response);
    }
    
    
/** Returns a short description of the servlet.
     
*/
    
public String getServletInfo() {
        
return "Short description";
    }
    
// </editor-fold>
}


在这里我们先得到了服务器所在的系统的字体,并用这些字体生成不同的字符,然后再随机设大小,随机变形,然后为字体加上渐变,并给整个图片添加干扰线条以及干扰点.让程序识别的难度加大.

呵呵,我们可以把它改成字母或者中文的验证,道理都是一样的,只不过在生成的时候,不一定用数字了,而是用所有可以输入的文字.这样,被程序识别的可能又小了.

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


网站导航: