自己动手实现一次性图片验证码

小编 2026-07-13 阅读:857 评论:0
  以前碰到注册登录需要图形验证码的时候,一般都是到网络上直接淘一个,也不读代码,直接就用了,今...

  以前碰到注册登录需要图形验证码的时候,一般都是到网络上直接淘一个,也不读代码,直接就用了,今天静下来,从头到尾读了一遍代码,自己又照着写了一遍,加上了完整的注释,下面介绍步骤,首先新建一个web项目,src新建一个class类:

  1 import java.awt.BasicStroke;  2 import java.awt.Color;  3 import java.awt.Font;  4 import java.awt.Graphics;  5 import java.awt.Graphics2D;  6 import java.awt.image.BufferedImage;  7 import java.io.FileNotFoundException;  8 import java.io.FileOutputStream;  9 import java.io.IOException; 10 import java.io.OutputStream; 11 import java.util.Random; 12  13 import javax.imageio.ImageIO; 14  15 public class VCode { 16  17     private int w;// 图片宽 18     private int h;// 图片高 19     private Color bgColor = new Color(240, 240, 240);// 背景色 20     private Random random = new Random();// 随机数对象 21     // 设置字体范围 22     private String[] fontNames = { "宋体", "华文楷体", "黑体", "华文新魏", "华文隶书", "微软雅黑", 23             "楷体" }; 24     //设置字体样式范围 25     private int[] fontstyles = { 0, 1, 2, 3 }; 26     //设置字号范围 27     private int[] fontSizes={24,25,26,27,28}; 28     //设置所有字符串范围 29     private String codes="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 30      31      32     //无参构造方法 33     public VCode() { 34     } 35      36     //带宽和高的构造函数  37     public VCode(int w, int h) { 38         super(); 39         this.w = w; 40         this.h = h; 41     } 42  43  44     // 返回一张背景图片 45     private BufferedImage createImage() { 46         /** 47          * 1:创建图片 2:设置背景色 48          */ 49         // 1:创建图片 50         BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 51         // 2:设置背景色 52         Graphics g = img.getGraphics(); 53         g.setColor(bgColor); 54         g.fillRect(0, 0, w, h); 55  56         return img; 57     } 58  59     // 随机返回字体颜色 60     private Color randomColor() { 61         int r = random.nextInt(256); 62         int g = random.nextInt(256); 63         int b = random.nextInt(256); 64         return new Color(r, g, b); 65     } 66  67     // 随机返回字体样式 68     private Font randomFont() { 69         //随机生成字体下标,随机从给定的范围内获取一个字体 70         int index=random.nextInt(fontNames.length); 71         String name=fontNames[index]; 72  73         //随机生成字体样式下表,随机从给定的返回内获取到一个字体样式 74         index=random.nextInt(fontstyles.length); 75         int style = fontstyles[index]; 76  77         //随机生成字体大小下标,随机从给定的返回内获取到一个字体大小 78         index=random.nextInt(fontSizes.length); 79         int size = fontSizes[index]; 80  81         return new Font(name, style, size); 82     } 83  84     // 随机返回字体内容 85     private String randomChar() { 86         int index=random.nextInt(codes.length()); 87          88         return codes.charAt(index)+""; 89     } 90  91     //随即返回几条干扰线 92     private void getLine(BufferedImage img){ 93         //设置干扰线的宽度为1.5倍宽,随机画五条 94         Graphics2D g=(Graphics2D)img.getGraphics(); 95         g.setColor(Color.BLACK); 96         g.setStroke(new BasicStroke(1.5f)); 97         for(int i=0;i<5;i++){ 98             int x1=random.nextInt(w); 99             int y1=random.nextInt(h);100             int x2=random.nextInt(w);101             int y2=random.nextInt(h);102             g.drawLine(x1, y1, x2, y2);103             104         }105         106     }107     // 用户调用该方法获取图片108     public BufferedImage getImage() {109         /**110          * 随机生成字符,字符范围0-9A-Za-z, 设置字体,字号,是否粗体 都是随机 字符的颜色111          */112         BufferedImage img = createImage();113 114         this.getLine(img);115         // 获取画笔116         Graphics g = img.getGraphics();117         // 画内容118         for (int i = 0; i < 4; i++) {119             g.setColor(this.randomColor());// 获取随机颜色120             g.setFont(this.randomFont());// 获取随机字体121             g.drawString(this.randomChar(), w / 4 * i, h - 5);// 获取字符串随机内容122         }123         return img;124     }125     126     //用户调用该方法保存图片到本地127     public void saveImage(BufferedImage img,OutputStream ous){128         129         try {130             ImageIO.write(img, "JPEG", ous);131         } catch (FileNotFoundException e) {132             e.printStackTrace();133         } catch (IOException e) {134             e.printStackTrace();135         }136     }137 }

接下来新建一个servlet:

 1 package com.wang.verifySode; 2  3 import java.awt.Color; 4 import java.awt.Font; 5 import java.awt.Graphics; 6 import java.awt.image.BufferedImage; 7 import java.io.FileOutputStream; 8 import java.io.IOException; 9 import java.io.PrintWriter;10 11 import javax.imageio.ImageIO;12 import javax.servlet.ServletException;13 import javax.servlet.http.HttpServlet;14 import javax.servlet.http.HttpServletRequest;15 import javax.servlet.http.HttpServletResponse;16 17 public class BServlet extends HttpServlet {18 19     public void doGet(HttpServletRequest request, HttpServletResponse response)20             throws ServletException, IOException {21         22         VCode v=new VCode(70, 35);23         BufferedImage img=v.getImage();24         v.saveImage(img, response.getOutputStream());25         26     }27 28 }

在你需要加验证码的地方,如注册页面中适当地方加入:

<img id="img" alt="" src="/tools/BServlet"><a href="javascript:changeNext()">看不清楚,换一张</a>

这里需要说一下,因为验证码有一个"看不清楚 换一张"的功能,所以需要加一个javascript函数,如下:

<script type="text/javascript">    function changeNext(){        var a=document.getElementById("img");        a.src="/tools/BServlet?a="+new Date().getTime();    }</script>

为了避免浏览器的图片缓存问题而导致点击后无法随机下一张图片,这里在超链接后面加一个永不重复的参数,可以避免这个问题,见上面代码.

配置项目,开浏览器,运行,完美~

 

版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
标签列表