在网页编程中,经常需要使用到附加码这样的一个东西,防止黑客用程序用穷举法去破解密码。下面是我的一个附加码的Servlet实现。
  1 import java.awt.*;
import java.awt.*;
  2 import java.awt.image.*;
import java.awt.image.*;
  3 import java.io.*;
import java.io.*;
  4 import java.util.Random;
import java.util.Random;
  5 import javax.servlet.*;
import javax.servlet.*;
  6 import javax.servlet.http.*;
import javax.servlet.http.*;
  7
  8 import com.sun.image.codec.jpeg.*;
import com.sun.image.codec.jpeg.*;
  9
 10
 public class KeyImage extends HttpServlet
public class KeyImage extends HttpServlet  {
{
 11
 12 private static final String CONTENT_TYPE = "text/html; charset=GBK";
  private static final String CONTENT_TYPE = "text/html; charset=GBK";
 13
 14 //Initialize global variables
  //Initialize global variables
 15
 public void init() throws ServletException
  public void init() throws ServletException  {
{
 16
 17 }
  }
 18
 19
 /**//**
  /**//**
 20 * 随机数生成器
   * 随机数生成器
 21 */
   */
 22 private static Random random = new Random();
  private static Random random = new Random();
 23
 24
 /**//**
  /**//**
 25 * 系统所有的字符
   * 系统所有的字符
 26 */
   */
 27 private static Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
  private static Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
 28
 29
 /**//**
  /**//**
 30 * 排除的一些字体(这些字体会显示不正常)
   * 排除的一些字体(这些字体会显示不正常)
 31 */
   */
 32 private static java.util.Set excludeFonts = new java.util.HashSet();
  private static java.util.Set excludeFonts = new java.util.HashSet();
 33
 34
 static
  static  {
{
 35 excludeFonts.add("Cursor");
    excludeFonts.add("Cursor");
 36 excludeFonts.add("Marlett");
    excludeFonts.add("Marlett");
 37 excludeFonts.add("Symbol");
    excludeFonts.add("Symbol");
 38 excludeFonts.add("Webdings");
    excludeFonts.add("Webdings");
 39 excludeFonts.add("Wingdings");
    excludeFonts.add("Wingdings");
 40 excludeFonts.add("Wingdings 2");
    excludeFonts.add("Wingdings 2");
 41 }
  }
 42
 43
 /**//**
  /**//**
 44 * 图片的宽度
   * 图片的宽度
 45 */
   */
 46 private static int imageWidth = 90;
  private static int imageWidth = 90;
 47
 48
 /**//**
  /**//**
 49 * 图片的高度
   * 图片的高度
 50 */
   */
 51 private static int imageHeight = 30;
  private static int imageHeight = 30;
 52
 53
 /**//**
  /**//**
 54 * 背景颜色
   * 背景颜色
 55 */
   */
 56 private static Color backgroundColor = Color.WHITE;
  private static Color backgroundColor = Color.WHITE;
 57
 58
 /**//**
  /**//**
 59 * 输出的字符数
   * 输出的字符数
 60 */
   */
 61 private static int characterNumber = 4;
  private static int characterNumber = 4;
 62
 63
 /**//**
  /**//**
 64 * 最终附加码的字符串
   * 最终附加码的字符串
 65 */
   */
 66 private StringBuffer keyBuf = null;
  private StringBuffer keyBuf = null;
 67
 68
 /**//**
  /**//**
 69 * 字符的颜色数组
   * 字符的颜色数组
 70 */
   */
 71
 private static Color[] colors = new Color[]
  private static Color[] colors = new Color[] {Color.BLACK, Color.BLUE,
{Color.BLACK, Color.BLUE,
 72 Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN, Color.MAGENTA,
      Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN, Color.MAGENTA,
 73 Color.RED};
      Color.RED};
 74
 75
 /**//**
  /**//**
 76 * 获得随机的X值(范围在5到9之间变化)
   * 获得随机的X值(范围在5到9之间变化)
 77 * @return int
   * @return int
 78 */
   */
 79
 private int randomX()
  private int randomX()  {
{
 80 return random.nextInt(5) + 5;
    return random.nextInt(5) + 5;
 81 }
  }
 82
 83
 /**//**
  /**//**
 84 * 获得随机的Y值(范围在20到24之间变化)
   * 获得随机的Y值(范围在20到24之间变化)
 85 * @return int
   * @return int
 86 */
   */
 87
 private int randomY()
  private int randomY()  {
{
 88 return random.nextInt(5) + 20;
    return random.nextInt(5) + 20;
 89 }
  }
 90
 91
 /**//**
  /**//**
 92 * 随机产生字符的大小
   * 随机产生字符的大小
 93 * @return int 随机字符大小
   * @return int 随机字符大小
 94 */
   */
 95
 private int randomSize()
  private int randomSize()  {
{
 96 return random.nextInt(5) + 20;
    return random.nextInt(5) + 20;
 97 }
  }
 98
 99
 /**//**
  /**//**
100 * 随机产生Font实例
   * 随机产生Font实例
101 * @return Font 随机Font实例
   * @return Font 随机Font实例
102 */
   */
103
 private Font randomFont()
  private Font randomFont()  {
{
104 Font font = null;
    Font font = null;
105
106
 if (fonts != null)
    if (fonts != null)  {
{
107 font = fonts[random.nextInt(fonts.length)];
      font = fonts[random.nextInt(fonts.length)];
108 font = font.deriveFont(random.nextInt(3), randomSize());
      font = font.deriveFont(random.nextInt(3), randomSize());
109
 } else
    } else  {
{
110 font = new Font("Arial Black", Font.PLAIN, 15);
      font = new Font("Arial Black", Font.PLAIN, 15);
111 }
    }
112
113
 while (excludeFonts.contains(font.getName()))
    while (excludeFonts.contains(font.getName()))  {
{
114
 if (fonts != null)
      if (fonts != null)  {
{
115 font = fonts[random.nextInt(fonts.length)];
        font = fonts[random.nextInt(fonts.length)];
116 font = font.deriveFont(random.nextInt(3), randomSize());
        font = font.deriveFont(random.nextInt(3), randomSize());
117
 } else
      } else  {
{
118 font = new Font("Arial Black", Font.PLAIN, 15);
        font = new Font("Arial Black", Font.PLAIN, 15);
119 }
      }
120 }
    }
121
122 log("Current Font: " + font.getName() + " Family: " + font.getFamily() + " Font Name: " + font.getFontName());
    log("Current Font: " + font.getName() + " Family: " + font.getFamily() + " Font Name: " + font.getFontName());
123
124 return font;
    return font;
125 }
  }
126
127
 /**//**
  /**//**
128 * 随机生成一个Color实例(除了背景)
   * 随机生成一个Color实例(除了背景)
129 * @return Color 随机Color实例
   * @return Color 随机Color实例
130 */
   */
131
 private Color randomColor()
  private Color randomColor()  {
{
132 int index = random.nextInt(colors.length);
    int index = random.nextInt(colors.length);
133 log("Color index is: " + index);
    log("Color index is: " + index);
134
135 return colors[index];
    return colors[index];
136 }
  }
137
138
 /**//**
  /**//**
139 * 写入一个字符
   * 写入一个字符
140 * @param g Graphics
   * @param g Graphics
141 * @param x int
   * @param x int
142 * @param y int
   * @param y int
143 */
   */
144
 private void drawCharacter(Graphics g, int x, int y)
  private void drawCharacter(Graphics g, int x, int y)  {
{
145 int ri = (int) (Math.random() * 10);    // 随机生成的数字
    int ri = (int) (Math.random() * 10);    // 随机生成的数字
146 keyBuf.append(ri);
    keyBuf.append(ri);
147 g.setColor(randomColor());
    g.setColor(randomColor());
148 g.setFont(randomFont());
    g.setFont(randomFont());
149 g.drawString(String.valueOf(ri), x, y);
    g.drawString(String.valueOf(ri), x, y);
150 }
  }
151
152
 /**//**
  /**//**
153 * 绘制背景
   * 绘制背景
154 * @param g Graphics
   * @param g Graphics
155 * @param color Color
   * @param color Color
156 * @param x int
   * @param x int
157 * @param y int
   * @param y int
158 * @param width int
   * @param width int
159 * @param height int
   * @param height int
160 */
   */
161 private void drawBackground(Graphics g, Color color, int x, int y, int width,
  private void drawBackground(Graphics g, Color color, int x, int y, int width,
162
 int height)
                              int height)  {
{
163 g.setColor(color);
    g.setColor(color);
164 g.fillRect(x, y, width, height);
    g.fillRect(x, y, width, height);
165 }
  }
166
167
 /**//**
  /**//**
168 * 绘制干扰点,干扰线
   * 绘制干扰点,干扰线
169 * @param g Graphics
   * @param g Graphics
170 * @param width int
   * @param width int
171 * @param height int
   * @param height int
172 */
   */
173
 private void drawInterrupt(Graphics g, int width, int height)
  private void drawInterrupt(Graphics g, int width, int height)  {
{
174 int numbers = random.nextInt(100) + 50;    // 50到149个干扰点
    int numbers = random.nextInt(100) + 50;    // 50到149个干扰点
175 g.setColor(Color.BLACK);
    g.setColor(Color.BLACK);
176
177
 for (int i = 0; i < numbers; i++)
    for (int i = 0; i < numbers; i++)  {
{
178 g.fillRect(random.nextInt(width), random.nextInt(height), 1, 1);
      g.fillRect(random.nextInt(width), random.nextInt(height), 1, 1);
179 }
    }
180
181 g.drawLine(0, random.nextInt(height), width, random.nextInt(height));
    g.drawLine(0, random.nextInt(height), width, random.nextInt(height));
182 }
  }
183
184
 /**//**
  /**//**
185 * Process the HTTP Get request
   * Process the HTTP Get request
186 * 随机生成数字的策略:
   * 随机生成数字的策略:
187 * 1.随机渐变色(包括文字和背景,暂时不实现)
   * 1.随机渐变色(包括文字和背景,暂时不实现)
188 * 2.所有可打印字符(这里暂时用数字)
   * 2.所有可打印字符(这里暂时用数字)
189 * 3.字符大小随机变化
   * 3.字符大小随机变化
190 * 4.位置不固定
   * 4.位置不固定
191 * 5.象素行或列随机错位
   * 5.象素行或列随机错位
192 * @param request HttpServletRequest
   * @param request HttpServletRequest
193 * @param response HttpServletResponse
   * @param response HttpServletResponse
194 * @throws ServletException
   * @throws ServletException
195 * @throws IOException
   * @throws IOException
196 */
   */
197 public void doGet(HttpServletRequest request, HttpServletResponse response)
  public void doGet(HttpServletRequest request, HttpServletResponse response)
198
 throws ServletException, IOException
      throws ServletException, IOException  {
{
199
200 BufferedImage image = new BufferedImage(imageWidth, imageHeight,
    BufferedImage image = new BufferedImage(imageWidth, imageHeight,
201 BufferedImage.TYPE_INT_RGB);
                                            BufferedImage.TYPE_INT_RGB);
202 Graphics g = image.getGraphics();
    Graphics g = image.getGraphics();
203
204 drawBackground(g, backgroundColor, 0, 0, imageWidth, imageHeight);
    drawBackground(g, backgroundColor, 0, 0, imageWidth, imageHeight);
205
206 keyBuf = new StringBuffer();
    keyBuf = new StringBuffer();
207 int offset = 0;   // 偏移量
    int offset = 0;   // 偏移量
208
 for (int i = 0; i < characterNumber; i++)
    for (int i = 0; i < characterNumber; i++)  {
{
209 drawCharacter(g, randomX() + offset, randomY());
      drawCharacter(g, randomX() + offset, randomY());
210 offset += imageWidth / characterNumber;
      offset += imageWidth / characterNumber;
211 }
    }
212
213 drawInterrupt(g, imageWidth, imageHeight);
    drawInterrupt(g, imageWidth, imageHeight);
214
215 response.setHeader("Cache-Control", "no-store");
    response.setHeader("Cache-Control", "no-store");
216 response.setDateHeader("Expires", 0);
    response.setDateHeader("Expires", 0);
217 response.setContentType("image/jpeg");
    response.setContentType("image/jpeg");
218
219 ServletOutputStream out = response.getOutputStream();
    ServletOutputStream out = response.getOutputStream();
220
221 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
222 encoder.encode(image);
    encoder.encode(image);
223 out.close();
    out.close();
224
225 // 保存附加码
    // 保存附加码
226 request.getSession().setAttribute("_key", keyBuf.toString());
    request.getSession().setAttribute("_key", keyBuf.toString());
227 log("The addtional code is: " + keyBuf.toString());
    log("The addtional code is: " + keyBuf.toString());
228 }
  }
229
230 //Clean up resources
  //Clean up resources
231
 public void destroy()
  public void destroy()  {
{
232 }
  }
233
234
 /**//**
  /**//**
235 * 改写服务器日志的输出
   * 改写服务器日志的输出
236 * @param msg String 要输出的信息
   * @param msg String 要输出的信息
237 */
   */
238
 public void log(String msg)
  public void log(String msg)  {
{
239 super.log(msg);
    super.log(msg);
240 }
  }
241
242
 /**//**
  /**//**
243 * 改写服务器日志的输出
   * 改写服务器日志的输出
244 * @param message String 要输出的信息
   * @param message String 要输出的信息
245 * @param t Throwable 抛出的意外
   * @param t Throwable 抛出的意外
246 */
   */
247
 public void log(String message, Throwable t)
  public void log(String message, Throwable t)  {
{
248 t.printStackTrace(System.out);
    t.printStackTrace(System.out);
249 super.log(message, t);
    super.log(message, t);
250 }
  }
251 }
}        附加码的效果图:
 
	posted on 2005-05-12 15:33 
小米 阅读(1433) 
评论(4)  编辑  收藏  所属分类: 
Java