使用java随机生成验证码

使用java随机生成验证码


作者:传智播客Java培训学院
首发:http://www.itcast.cn/javaee

生成验证码图片
验证码是Completely Automated Public Turing test to tell Computers and Humans Apart(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序,可以防止:恶意破解密码、刷票、论坛灌水、有效防止某个黑客对某一特定注册用户,用特定程序暴力破解方式进行不断的登录尝试。实际上验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能。
下面我们就来学习如何自动生成一个验证码图片,案例的源代码点击此处进行下载,具体如下:

1.生成字符验证码

大家想必在登录某个网站的时候都输入过验证码,如图1-1所示:

1-1 验证码

下面通过一个案例来学习如何自动生成一个验证码图片:
(1)创建一个web应用,名称为Example1,在该应用下的src目录下新建一个Class类,名称为ImageTest,主要代码如例1-1所示:
1-1 ImageTest.java

public class ImageTest {

    @Test
public void fun1() throws FileNotFoundExceptionIOException{

       /*
        * 1. 创建图片缓冲区
        * 2. 设置其宽高
        * 3. 得到这个图片的绘制环境(得到画笔)
        * 4. 保存起来
        */
       BufferedImage bi = new BufferedImage(70, 35, BufferedImage.TYPE_INT_RGB);
       Graphics2D g = (Graphics2D)bi.getGraphics();//得到绘制环境
       g.setColor(Color.WHITE);//把环境设置为白色
       g.fillRect(0, 0, 70, 35);//填充矩形!填充矩形,从0,0点开始,宽70,高35,即整个图片,即为图片设置背景色
       g.setColor(Color.RED);//把环境设置为红色
       g.drawString(“Hello”, 2, 35-2);//向图片上写入字符串,其中2,2表示x,y轴的坐标
       ImageIO.write(bi, “JPEG”, new FileOutputStream(“F:/xxx.jpg”));
}
}

在例1-1中,首先要获得图片缓冲区,即BufferedImage类的一个对象,BufferedImage类的构造方法中,第一个参数和第二个参数表示图片的长和宽,第三个参数是图片的类型;然后获取绘制环境,也可以理解为获取当前图片的画笔,使用该对象可以设置一系列的属性,例如图片的背景颜色、填充形状等。最后使用ImageIO类的write()方法将当前画好的图片写到指定的输出流中。
(2)测试fun1()方法,去F盘查看生成的图片效果如何,如图1-2所示:

1-2 绘制的图片
如图1-2所示,绘制的图片背景色是白色,字符串“Hello”的颜色是红色,该字符串的位置也是由我们自己设置的,可以调整。

2.生成字母验证码

通过以上对自动绘制图片的了解,下面我们来完成另外一个绘制图片的类,这个类相较于上面的ImageTest类要复杂很多,如下所示:
(1)ImageTest同包下新建一个Class类,名称为VerifyCode,下面我们对类中的方法进行一一介绍。首先来看该类的成员变量,如例1-2所示:
1-2 VerifyCode.java类中的成员变量

public class VerifyCode {

    private int w = 70;
    private int h = 35;
    private Random r = new Random();
    // {“宋体”, “华文楷体”, “黑体”, “华文新魏”, “华文隶书”, “微软雅黑”, “楷体_GB2312”}
    private String[] fontNames  = {“宋体”, “华文楷体”, “黑体”, “微软雅黑”, “楷体_GB2312”};
    // 可选字符
    private String codes=“23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUV
                              WXYZ”;
    // 背景色
    private Color bgColor  = new Color(255, 255, 255);
    // 验证码上的文本
    private String text ;

1-2中,成员变量wh分别表示图片的长和宽;成员变量rRandom类型的对象,用来生成随机数;成员变量fontNames是列举验证图片中验证码的字体类型;成员变量codes是列举验证码的所有的可选字符;成员变量bgColor是验证图片的背景色;成员变量text是图片上的验证码。
(2)VerifyCode类的生成随机颜色的方法,主要代码如例1-3所示:
1-3  randomColor()方法

    // 生成随机的颜色
private Color randomColor () {

       int red = r.nextInt(150);
       int green = r.nextInt(150);
       int blue = r.nextInt(150);
       return new Color(red, green, blue);
}

1-3中,rRandom类型的对象,r.nextInt(int n)方法返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值n(不包括)之间均匀分布的 int值。其中局部变量redgreenblue分别代表颜色的RGB的红、绿、蓝三个通道的颜色值。该方法返回的是随机产生的颜色。
(3)VerifyCode类的生成随机字体的方法,主要代码如例1-4所示:
1-4  randomFont()方法

// 生成随机的字体
private Font randomFont () {

           int index = r.nextInt(fontNames.length);
           String fontName = fontNames[index];//生成随机的字体名称
           int style = r.nextInt(4);//生成随机的样式, 0(无样式), 1(粗体), 2(斜体), 3(粗体+斜体)
           int size = r.nextInt(5) + 24; //生成随机字号, 24 ~ 28
           return new Font(fontName, style, size);
}

1-4中,r.nextInt(fontNames.length)方法是获得一个从0到成员变量fontNames数组的长度之间的整数index,然后将这个整数当作fontNames数组的下标,找到对应的字体类型。局部变量style是随机产生的样式,详情可参考例1-4中的代码注释,局部变量size是随机生成的字体大小,即字号,范围是从24~28;最后将该字体返回。
(4)VerifyCode类的生成随机的干扰线方法,主要代码如例1-5所示:
1-5 drawLine()方法

  // 画干扰线
private void drawLine (BufferedImage image) {

       int num  = 3;//一共画3条
       Graphics2D g2 = (Graphics2D)image.getGraphics();
       for(int i = 0; i < num; i++) {//生成两个点的坐标,即4个值
           int x1 = r.nextInt(w);
           int y1 = r.nextInt(h);
           int x2 = r.nextInt(w);
           int y2 = r.nextInt(h);
           g2.setStroke(new BasicStroke(1.5F));
           g2.setColor(Color.BLUE); //干扰线是蓝色
           g2.drawLine(x1, y1, x2, y2);//画线
       }
}

1-5中,局部变量num是记录干扰线的条数,然后创建当前图片的画笔Graphics2D类的对象,再利用r对象生成四个值,其中x1x2的大小范围在0~70之间,y1y2的大小在0~35之间,这四个值是用来作为确定一条直线的两个点的坐标,由于有三条干扰线,所以这里使用for循环,然后每循环一次就使用画笔对象g2drawLine()方法绘制一条线。
(5)VerifyCode类的生成随机字符的方法,主要代码如例1-6所示:

// 随机生成一个字符
private char randomChar () {

       int index = r.nextInt(codes.length());
       return codes.charAt(index);
}

1-6中,验证码的所有可选字符都在字符串codes中,通过r对象的nextInt()方法获得一个在0codes.length范围内的整数index,然后调用charAt(index)方法获得指定索引的字符,并返回。
(6)VerifyCode类的创建BufferedImage的方法,主要代码如例1-7所示:

    // 创建BufferedImage
private BufferedImage createImage () {

       BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
       Graphics2D g2 = (Graphics2D)image.getGraphics();
       g2.setColor(this.bgColor);
       g2.fillRect(0, 0, w, h);
       return image;
}

1-7中,创建BufferedImage对象的步骤与例1-1相同,最后将创建的对象返回。
(7)VerifyCode类的获得验证码图片上的文本方法,主要代码如例1-8所示:

    // 返回验证码图片上的文本
public String getText () {

       return text;
}

1-8中的text是成员变量,代表图片上的验证码。该方法要在另一个方法getImage()调用之后调用,getImage()方法后面会详解。
(8)VerifyCode类的将图片保存到指定的输出流,主要代码如例1-9所示:

    // 保存图片到指定的输出流
public static void output (BufferedImage image, OutputStream out)
              throws IOException {

       ImageIO.write(image, “JPEG”, out);
}

1-9中,output()方法有两个参数,第一个参数是绘制的图片,第二个参数是图片将要保存的输出流;使用ImageIO类的write()方法将image对象以JPEG的格式保存在out输出流中。
(9)VerifyCode类的得到验证码图片的方法,主要代码如例1-10所示:

    // 调用这个方法得到验证码
public BufferedImage getImage () {

       BufferedImage image = createImage();//创建图片缓冲区
       Graphics2D g2 = (Graphics2D)image.getGraphics();//得到绘制环境
       StringBuilder sb = new StringBuilder();//用来装载生成的验证码文本
       // 向图片中画4个字符
       for(int i = 0; i < 4; i++)  {//循环四次,每次生成一个字符
           String s = randomChar() + “”;//随机生成一个字母
           sb.append(s); //把字母添加到sb
           float x = i * 1.0F * w / 4; //设置当前字符的x轴坐标
           g2.setFont(randomFont()); //设置随机字体
           g2.setColor(randomColor()); //设置随机颜色
           g2.drawString(s, x, h-5); //画图
       }
       this.text = sb.toString(); //把生成的字符串赋给了this.text
       drawLine(image); //添加干扰线
       return image;    
}

1-10中,先调用createImage()方法创建图片缓冲区,然后得到绘制环境,即当前图片的画笔;再创建一个用来保存验证码文本的StringBuilder对象,利用for循环及以上提到的方法向图片中画4个字符,然后将sb对象的值赋给成员变量text,这时调用例1-8中的getText()方法就可以获得验证码文本。最后添加干扰线,再返回image对象。
(10)以上就是VerifyCode类的所有方法,现在我们在ImageTest类中定义一个单元测试方法fun2(),该方法的主要内容如例1-11所示:

@Test
public void fun2() throws FileNotFoundException, IOException{

           VerifyCode vc = new VerifyCode();//创建VerifyCode类的对象
           BufferedImage bi = vc.getImage();//调用getImge()方法获得一个BufferedImage对象
           VerifyCode.output(bi, new FileOutputStream(“F:/验证码.jpg”));//调用静态方法output()方法将图片保存在文件输出流中
           System.out.println(vc.getText());//在控制台上打印验证码的文本值
}

(11)执行fun2()方法,控制台上打印结果如图1-3所示:

1-3 验证码信息
(12)由图1-3可知,验证码文本信息为“pxTy”,现在去F盘中找到验证码.jpg,打开如图1-4所示:

1-4 验证码
在以后的开发中,想获得验证码就可以把VerifyCode类当作一个帮助类,将它拷贝到自己的项目中然后调用相应的方法就可以获得验证码图片。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/100807.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • SP网站建立后.有两处地方需要首先修改

    SP网站建立后.有两处地方需要首先修改1.SP管理中心—-系统设置—-配置备用访问映射内部URL区域区域的公用URL http://kms:504 默认http://kms:504 http://localhost:504 Intranethttp://localhost:504 http://192.168.1.109:504 Internethttp://192.168.1.109:5

    2022年6月17日
    32
  • hashmap线程不安全问题_java多线程编程面试题

    hashmap线程不安全问题_java多线程编程面试题https://blog.csdn.net/swl1993831/article/details/91896811

    2022年10月11日
    4
  • 搭建Eurake集群

    搭建Eurake集群eureka作为SpringCloud的服务发现与注册中心,在整个的微服务体系中,处于核心位置。单一的eureka服务,显然不能满足高可用的实际生产环境,这就要求我们配置一个能够应对各种突发情况,具有较强容灾能力的eureka集群服务。其实我们只需要在部署时候,对eureka的配置文件做相应的修改,运行即可。在项目中,创建三个名字分别为eureka01,eureka02,eureka03的eur…

    2022年6月4日
    41
  • 微信不能登录网页版(微信手机网页登录)

     因为出于工作和学习的目的,我的个人电脑操作系统使用的是Ubuntu18.04LTS,就目前而言,许多优秀的软件都有Linux版本,虽然Linux的用户相对群体较小,但是其软件生态也在逐渐成长,而且日常使用浏览器就可以解决许多的应用需求。现在微信和QQ在生活和工作领域均是举足轻重,emm…  BUT!!!腾讯到目前为止并没有推出Linux版的微信和TI…

    2022年4月12日
    61
  • [数据仓库]分层概念,ODS,DM,DWD,DWS,DIM的概念「建议收藏」

    [数据仓库]分层概念,ODS,DM,DWD,DWS,DIM的概念「建议收藏」ODS是什么?ODS全称是OperationalDataStore,操作数据存储.“面向主题的”,数据运营层,也叫ODS层,是最接近数据源中数据的一层,数据源中的数据,经过抽取、洗净、传输,也就说传说中的ETL之后,装入本层。本层的数据,总体上大多是按照源头业务系统的分类方式而分类的。但是,这一层面的数据却不等同于原始数据。在源数据装入这一层时,要进行诸如去噪(例如有一条数据中人的年龄是300岁,这种属于异常数据,就需要提前做一些处理)、去重(例如在个人资料表中,同一ID却有两条重复

    2022年4月19日
    110
  • tomcat严重: Error filterStart

    tomcat严重: Error filterStart如果是连接到cvs是jar包的路径问题。。。。删除从CVS导入的jar包,再导入本机上的jar包….

    2022年7月27日
    13

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号