隨筆-57  評論-202  文章-17  trackbacks-0
                在網頁編程中,經常需要使用到附加碼這樣的一個東西,防止黑客用程序用窮舉法去破解密碼。下面是我的一個附加碼的Servlet實現。

            1import java.awt.*;
            2import java.awt.image.*;
            3import java.io.*;
            4import java.util.Random;
            5import javax.servlet.*;
            6import javax.servlet.http.*;
            7
            8import com.sun.image.codec.jpeg.*;
            9
           10public class KeyImage extends HttpServlet {
           11
           12  private static final String CONTENT_TYPE = "text/html; charset=GBK";
           13
           14  //Initialize global variables
           15  public void init() throws ServletException {
           16
           17  }

           18
           19  /**
           20   * 隨機數生成器
           21   */

           22  private static Random random = new Random();
           23
           24  /**
           25   * 系統所有的字符
           26   */

           27  private static Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
           28
           29  /**
           30   * 排除的一些字體(這些字體會顯示不正常)
           31   */

           32  private static java.util.Set excludeFonts = new java.util.HashSet();
           33
           34  static {
           35    excludeFonts.add("Cursor");
           36    excludeFonts.add("Marlett");
           37    excludeFonts.add("Symbol");
           38    excludeFonts.add("Webdings");
           39    excludeFonts.add("Wingdings");
           40    excludeFonts.add("Wingdings 2");
           41  }

           42
           43  /**
           44   * 圖片的寬度
           45   */

           46  private static int imageWidth = 90;
           47
           48  /**
           49   * 圖片的高度
           50   */

           51  private static int imageHeight = 30;
           52
           53  /**
           54   * 背景顏色
           55   */

           56  private static Color backgroundColor = Color.WHITE;
           57
           58  /**
           59   * 輸出的字符數
           60   */

           61  private static int characterNumber = 4;
           62
           63  /**
           64   * 最終附加碼的字符串
           65   */

           66  private StringBuffer keyBuf = null;
           67
           68  /**
           69   * 字符的顏色數組
           70   */

           71  private static Color[] colors = new Color[]{Color.BLACK, Color.BLUE,
           72      Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN, Color.MAGENTA,
           73      Color.RED}
          ;
           74
           75  /**
           76   * 獲得隨機的X值(范圍在5到9之間變化)
           77   * @return int
           78   */

           79  private int randomX() {
           80    return random.nextInt(5+ 5;
           81  }

           82
           83  /**
           84   * 獲得隨機的Y值(范圍在20到24之間變化)
           85   * @return int
           86   */

           87  private int randomY() {
           88    return random.nextInt(5+ 20;
           89  }

           90
           91  /**
           92   * 隨機產生字符的大小
           93   * @return int 隨機字符大小
           94   */

           95  private int randomSize() {
           96    return random.nextInt(5+ 20;
           97  }

           98
           99  /**
          100   * 隨機產生Font實例
          101   * @return Font 隨機Font實例
          102   */

          103  private Font randomFont() {
          104    Font font = null;
          105
          106    if (fonts != null{
          107      font = fonts[random.nextInt(fonts.length)];
          108      font = font.deriveFont(random.nextInt(3), randomSize());
          109    }
           else {
          110      font = new Font("Arial Black", Font.PLAIN, 15);
          111    }

          112
          113    while (excludeFonts.contains(font.getName())) {
          114      if (fonts != null{
          115        font = fonts[random.nextInt(fonts.length)];
          116        font = font.deriveFont(random.nextInt(3), randomSize());
          117      }
           else {
          118        font = new Font("Arial Black", Font.PLAIN, 15);
          119      }

          120    }

          121
          122    log("Current Font: " + font.getName() + " Family: " + font.getFamily() + " Font Name: " + font.getFontName());
          123
          124    return font;
          125  }

          126
          127  /**
          128   * 隨機生成一個Color實例(除了背景)
          129   * @return Color 隨機Color實例
          130   */

          131  private Color randomColor() {
          132    int index = random.nextInt(colors.length);
          133    log("Color index is: " + index);
          134
          135    return colors[index];
          136  }

          137
          138  /**
          139   * 寫入一個字符
          140   * @param g Graphics
          141   * @param x int
          142   * @param y int
          143   */

          144  private void drawCharacter(Graphics g, int x, int y) {
          145    int ri = (int) (Math.random() * 10);    // 隨機生成的數字
          146    keyBuf.append(ri);
          147    g.setColor(randomColor());
          148    g.setFont(randomFont());
          149    g.drawString(String.valueOf(ri), x, y);
          150  }

          151
          152  /**
          153   * 繪制背景
          154   * @param g Graphics
          155   * @param color Color
          156   * @param x int
          157   * @param y int
          158   * @param width int
          159   * @param height int
          160   */

          161  private void drawBackground(Graphics g, Color color, int x, int y, int width,
          162                              int height) {
          163    g.setColor(color);
          164    g.fillRect(x, y, width, height);
          165  }

          166
          167  /**
          168   * 繪制干擾點,干擾線
          169   * @param g Graphics
          170   * @param width int
          171   * @param height int
          172   */

          173  private void drawInterrupt(Graphics g, int width, int height) {
          174    int numbers = random.nextInt(100+ 50;    // 50到149個干擾點
          175    g.setColor(Color.BLACK);
          176
          177    for (int i = 0; i < numbers; i++{
          178      g.fillRect(random.nextInt(width), random.nextInt(height), 11);
          179    }

          180
          181    g.drawLine(0, random.nextInt(height), width, random.nextInt(height));
          182  }

          183
          184  /**
          185   * Process the HTTP Get request
          186   * 隨機生成數字的策略:
          187   * 1.隨機漸變色(包括文字和背景,暫時不實現)
          188   * 2.所有可打印字符(這里暫時用數字)
          189   * 3.字符大小隨機變化
          190   * 4.位置不固定
          191   * 5.象素行或列隨機錯位
          192   * @param request HttpServletRequest
          193   * @param response HttpServletResponse
          194   * @throws ServletException
          195   * @throws IOException
          196   */

          197  public void doGet(HttpServletRequest request, HttpServletResponse response)
          198      throws ServletException, IOException {
          199
          200    BufferedImage image = new BufferedImage(imageWidth, imageHeight,
          201                                            BufferedImage.TYPE_INT_RGB);
          202    Graphics g = image.getGraphics();
          203
          204    drawBackground(g, backgroundColor, 00, imageWidth, imageHeight);
          205
          206    keyBuf = new StringBuffer();
          207    int offset = 0;   // 偏移量
          208    for (int i = 0; i < characterNumber; i++{
          209      drawCharacter(g, randomX() + offset, randomY());
          210      offset += imageWidth / characterNumber;
          211    }

          212
          213    drawInterrupt(g, imageWidth, imageHeight);
          214
          215    response.setHeader("Cache-Control""no-store");
          216    response.setDateHeader("Expires"0);
          217    response.setContentType("image/jpeg");
          218
          219    ServletOutputStream out = response.getOutputStream();
          220
          221    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
          222    encoder.encode(image);
          223    out.close();
          224
          225    // 保存附加碼
          226    request.getSession().setAttribute("_key", keyBuf.toString());
          227    log("The addtional code is: " + keyBuf.toString());
          228  }

          229
          230  //Clean up resources
          231  public void destroy() {
          232  }

          233
          234  /**
          235   * 改寫服務器日志的輸出
          236   * @param msg String 要輸出的信息
          237   */

          238  public void log(String msg) {
          239    super.log(msg);
          240  }

          241
          242  /**
          243   * 改寫服務器日志的輸出
          244   * @param message String 要輸出的信息
          245   * @param t Throwable 拋出的意外
          246   */

          247  public void log(String message, Throwable t) {
          248    t.printStackTrace(System.out);
          249    super.log(message, t);
          250  }

          251}

                附加碼的效果圖:
          adcode.JPG
          posted on 2005-05-12 15:33 小米 閱讀(1415) 評論(4)  編輯  收藏 所屬分類: Java

          評論:
          # re: 我的網頁附加碼實現 2008-08-22 12:07 | hjhgj
          hgjhg  回復  更多評論
            
          # 呵呵[未登錄] 2008-12-11 09:56 | 呵呵
          忿忿地說  回復  更多評論
            
          # re: 我的網頁附加碼實現 2009-10-23 20:00 | 44
          01  回復  更多評論
            
          # re: 我的網頁附加碼實現 2010-04-09 16:26 | cqhongde
          這類型附加碼識別率應該在95%以上  回復  更多評論
            
          主站蜘蛛池模板: 兴国县| 平武县| 康保县| 土默特左旗| 浑源县| 浙江省| 宜兴市| 中阳县| 曲阜市| 肥西县| 岫岩| 盐源县| 临江市| 读书| 沁阳市| 阿巴嘎旗| 祥云县| 太湖县| 柯坪县| 磴口县| 徐闻县| 吴忠市| 汶上县| 黑水县| 和政县| 东阳市| 龙南县| 双牌县| 宁强县| 饶阳县| 武义县| 万载县| 南阳市| 哈尔滨市| 团风县| 泰州市| 讷河市| 拜城县| 盐边县| 福清市| 贺兰县|