用java生成附加码 
  
   现在一些网站登陆的时候都需要用户添加附加码,这样是保护用户,防止黑客通过野蛮攻击获得用户信息(用户名称和口令,以前我用java做过一个野蛮攻击的程序来攻击一些网站来获得用户密码^_^)。下面例子是我实现附加码的方法,希望能起到启发作用! 
   刚开始我想用applet来实现附加码,这个实现方案的优点是实现速度快、图片的生成在客户端执行不必访问服务器;但是这个方案的最大缺点是容易泄密(用户可以下载applet,通过反编译可以知道附加码的实现算法,进而可以通过蛮力攻击而进入系统),所以没有采用。 
   因为逻辑在客户端实现容易造成泄密,所以逻辑现实应该在服务器端来实现,我采用了小服务servlet。下面是实现的源代码:Picture.java、CreateImage.java和CreateImage.jsp 
  
//读取服务器端的图片,在图片上画用户需要输入的附加码 
package lqh.rmb.picture; 
  
import java.io.*; 
  
public class Picture{ 
  
  final int key=43; 
  final String error_format_int= "format of color is not rgb.sample \"212|232|0\""; 
  final String error_color_input="format of color(num|num|num): num in 0-255"; 
  
  /**格式化输出数据**/ 
  public String manage(String temp){ 
    String returnStr=""; 
    temp = encrypt(temp); 
    byte[] by =temp.getBytes(); 
    for(int i=0;i<by.length;i++){ 
      returnStr=returnStr+(byte)by[i]+"|"; 
    } 
    return returnStr; 
  } 
  /**格式化输入数据**/ 
  public byte[] disManage(String temp){ 
    int len=0,index=0,i=0,first=0; 
    while(( i=temp.indexOf("|",first))>-1){ 
      len++; 
      first=i+1; 
    } 
    byte[] by=new byte[len]; 
    first=0; 
    while(( i=temp.indexOf("|",first))>-1){ 
     by[index]=Byte.parseByte(temp.substring(first,i)); 
     index++; 
     first=i+1; 
    } 
    return by; 
  } 
 /**随机生成四位的附加码**/  
 public String getRandom(){ 
    int i1 = (int)(java.lang.Math.random()*10); 
    int i2 = (int)(java.lang.Math.random()*10); 
    int i3 = (int)(java.lang.Math.random()*10); 
    int i4 = (int)(java.lang.Math.random()*10); 
    return String.valueOf(i1)+String.valueOf(i2)+String.valueOf(i3)+String.valueOf(i4); 
  } 
  /**加密1:错位处理**/ 
  public String encrypt(String randomStr){ 
     String para=random()+randomStr.substring(0,1)+random()+random()+randomStr.substring(1,2); 
            para= para+random()+randomStr.substring(2); 
     return jiaMi(para); 
  } 
  /**得到随机数0-9之间**/ 
  private String random(){ 
    String temp = String.valueOf((int)(java.lang.Math.random()*10)); 
    return temp; 
  } 
  /**加密2:加密处理,此方法可以自己修改**/ 
  private String jiaMi(String str){ 
    byte[] by = str.getBytes(); 
    ByteArrayInputStream in = new ByteArrayInputStream(by); 
    int ch; 
    int index=0; 
    byte[] temp = new byte[in.available()]; 
    while((ch=in.read())!=-1){ 
      temp[index]=(byte)(ch-key); 
      index++; 
    } 
    ByteArrayInputStream ins = new ByteArrayInputStream(temp); 
    DataInputStream inss=new DataInputStream(ins); 
    try{ return  inss.readLine();}catch(Exception e){return "";} 
  } 
  /**从给的数字里得到正确的数字**/ 
  public String discrypt(String temp){ 
    String para = jieMi(disManage(temp)); 
    return para.substring(1,2)+para.substring(4,5)+ para.substring(6,8); 
  } 
  /**解密处理**/ 
  private String jieMi(byte[] by){ 
    ByteArrayInputStream in = new ByteArrayInputStream(by); 
    int ch; 
    int index=0; 
    byte[] temp = new byte[in.available()]; 
    while((ch=in.read())!=-1){ 
      temp[index]=(byte)(ch+key); 
      index++; 
    } 
    ByteArrayInputStream ins = new ByteArrayInputStream(temp); 
    DataInputStream inss=new DataInputStream(ins); 
   try{ return inss.readLine();}catch(Exception e){return "";} 
  } 
  /**分解rgb格式的颜色 num|num|num**/ 
  public int[] masterData(String temp){ 
    int index_len=0,index=0,next_index=0; 
    int[] return_arr=new int[3]; 
    boolean break_error=false; 
    if(getMax(temp,"|")==2){ 
      while((index_len=temp.indexOf("|",next_index))>-1){ 
        if(getInt(temp.substring(next_index,index_len))==256){ 
          break_error = true; 
        }else{ 
          return_arr[index]=getInt(temp.substring(next_index,index_len)); 
          next_index=index_len+1; 
          index++; 
        } 
        if(break_error) break; 
      } 
      if(break_error){ 
        return null; 
      }else{ 
        return_arr[index] = getInt(temp.substring(next_index)); 
        return return_arr; 
      } 
    }else{ 
      System.out.println(error_format_int+":"+temp); 
      return null; 
    } 
  } 
  private int getMax(String temp,String temp2){ 
    int index=0,index_len=0,index_next=0; 
    while((index=temp.indexOf(temp2,index_next))>-1){ 
      index_len++; 
      index_next=index+1; 
    } 
    return index_len; 
  } 
  private int getInt(String temp){ 
    try{ 
       return Integer.parseInt(temp); 
    }catch(Exception e){ 
       System.out.println(error_color_input+":"+temp); 
       return 256; 
    } 
  } 
} 
  
下面是一个Servlet来响应客户,返回给客户一个做好的图片: 
package lqh.rmb.picture; 
  
import java.io.*; 
import java.util.*; 
import javax.servlet.*; 
import javax.servlet.http.*; 
import java.awt.*; 
import java.awt.image.*; 
import java.awt.image.BufferedImage; 
import com.sun.image.codec.jpeg.*; 
import com.sun.image.codec.jpeg.JPEGCodec; 
  
public class CreateImage extends HttpServlet { 
  static final private String CONTENT_TYPE = "text/html; charset=gb2312"; 
  final String input_back_color_error="input rgb backcolor is error"; 
  final String input_fore_color_error="input rgb forecolor is error"; 
  
  private Picture pic = new Picture(); 
  
  //Initialize global variables 
  public void init() throws ServletException { 
  } 
  //Process the HTTP Get request 
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    String queryNum   = request.getParameter("Image"); 
    String queryRgb=""; 
    if(request.getParameter("Rgb")!=null){ 
       queryRgb   = request.getParameter("Rgb"); 
    } 
    response.setHeader("Cache-Control","no-store"); 
    response.setContentType("image/jpeg"); 
    ServletOutputStream out=response.getOutputStream(); 
  
    //jpg格式的背景色图片(于页面风格一样),宽3.6毫米,高1.8毫米 
    InputStream imageIn = new FileInputStream(new File("D:/test.jpg")); 
    JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(imageIn); 
    BufferedImage image4 = decoder.decodeAsBufferedImage(); 
    queryNum = pic.discrypt(queryNum); 
    Graphics g = image4.getGraphics(); 
  
    if(queryRgb.length()>1){ 
      if(pic.masterData(queryRgb)!=null){ 
        int[] arg = pic.masterData(queryRgb); 
        g.setColor(new Color(arg[0],arg[1],arg[2])); 
      } 
    }else{ 
      g.setColor(new Color(255,0,0)); 
    } 
    g.drawString(queryNum,0,13); 
    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 
    encoder.encode(image4); 
    out.close(); 
  } 
  
} 
  
下面是一个jsp页面来验证结果: 
<%@ page contentType="text/html; charset=GBK" %> 
<%@ page import=" lqh.rmb.picture"%> 
<% 
  Picture pic = new Picture(); 
  String random =pic.getRandom(); 
  String encryRandom= pic.manage(random ); 
%> 
<html> 
<body> 
<%--这段代码可能需要自己来修改,才能调用到servlet--%> 
<img align=absbottom vspace=2 border=0 src="servlet/lqh.rmb.picture.CreateImage?Image=<%=encryRandom%>&Rgb=255|0|0" title="验证码图片">欢迎使用 
</body> 
</html>   
  
欢迎联系:[email protected]  
 
  |