图形验证码应该满足如下要求:
    A. 图形验证码里的字符并添加干扰线。
    B. 图形验证码应该动态生成,不重复,以防止根据图片hash进行内容匹配。
    C. 必须是一次性的,每次验证之后必须更新。
    D. 图形验证码对应的字符内容只能在服务端保存。
    E. 多样化的图形验证码只要具备安全特性,都可使用。

    1. String num = "4";
    2. int charNum = 4; // 随机产生字符数量
    3. if(num !=null){
    4. charNum = Integer.parseInt(num);
    5. }
    6. int width = 74; // 图片宽
    7. int height = 30; // 图片高
    8. int lineSize = 100; // 干扰线数量
    9. String randString = ""; //需要绘制的随机字符串
    10. BufferedImage buffImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); // BufferedImage类描述具有可访问图像数据缓冲区的Image
    11. Graphics2D g = buffImage.createGraphics();
    12. //设置背景色
    13. g.setColor(Color.white);
    14. g.fillRect(0,0,width,height);
    15. //设置字体
    16. g.setFont(new Font("Times New Roman",Font.ROMAN_BASELINE, 18));
    17. //画边框
    18. g.drawRect(0,0,width-1,height-1);
    19. //绘制干扰线
    20. Random random = new Random();
    21. for(int i = 0;i <=lineSize;i++)
    22. {
    23. int x = random.nextInt(width);
    24. int y = random.nextInt(height);
    25. int xl = random.nextInt(width / 8);
    26. int yl = random.nextInt(height / 8);
    27. g.setColor(randColor(130, 250));
    28. g.drawLine(x, y, x + xl, y + yl);
    29. }
    30. //字符集,从中随机产生字符串
    31. char[] characterSet = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    32. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
    33. g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.6f)); //设置透明色
    34. g.setFont(new Font("Fixedsys",Font.CENTER_BASELINE, 24));
    35. //产生随机验证码
    36. for(int i = 1;i <=charNum; i++)
    37. {
    38. g.setColor(randColor(20, 130));
    39. String rand = String.valueOf(characterSet[random.nextInt(characterSet.length)]); //获取随机的字符
    40. g.translate(random.nextInt(3), random.nextInt(3));
    41. g.drawString(rand, width / (charNum + 2) * i, height / 4 * 3);
    42. randString += rand;
    43. }
    44. g.dispose();
    45. System.out.println("验证码:"+randString);
    46. session.setAttribute("validateCode",randString);
    47. //禁止图像缓存。
    48. response.setHeader("Pragma","no-cache");
    49. response.setHeader("Cache-Control","no-cache");
    50. response.setDateHeader("Expires",0);
    51. OutputStream os = response.getOutputStream();
    52. try{
    53. ImageIO.write(buffImage, "png", os);
    54. os.close();
    55. out.clear();
    56. out = pageContext.pushBody();
    57. }catch(IOException e){
    58. e.printStackTrace();
    59. }
    60. /*
    61. * 随机获取颜色
    62. */
    63. private Color randColor(int fc, int bc) {
    64. Random random = new Random();
    65. if (fc > 255)
    66. fc = 255;
    67. if (bc > 255)
    68. bc = 255;
    69. int r = fc + random.nextInt(bc - fc);
    70. int g = fc + random.nextInt(bc - fc);
    71. int b = fc + random.nextInt(bc - fc);
    72. return new Color(r, g, b);
    73. }