用Java实现图片验证码功能

一、什么是图片验证码?

可以参考下面这张图:

我们在一些网站注册的时候,经常需要填写以上图片的信息。

1、图片生成实体类:

  1 package com.hexianwei.graphic;
  2 
  3 import java.awt.Color;
  4 import java.awt.Font;
  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 
 16 public class ImageVerificationCode {
 17 
 18     private int weight = 100;           //验证码图片的长和宽
 19     private int height = 40;
 20     private String text;                //用来保存验证码的文本内容
 21     private Random r = new Random();    //获取随机数对象
 22     //private String[] fontNames = {"宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312"};   //字体数组
 23     //字体数组
 24     private String[] fontNames = {"Georgia"};
 25     //验证码数组
 26     private String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
 27 
 28     /**
 29      * 获取随机的颜色
 30      *
 31      * @return
 32      */
 33     private Color randomColor() {
 34         int r = this.r.nextInt(225);  //这里为什么是225,因为当r,g,b都为255时,即为白色,为了好辨认,需要颜色深一点。
 35         int g = this.r.nextInt(225);
 36         int b = this.r.nextInt(225);
 37         return new Color(r, g, b);            //返回一个随机颜色
 38     }
 39 
 40     /**
 41      * 获取随机字体
 42      *
 43      * @return
 44      */
 45     private Font randomFont() {
 46         int index = r.nextInt(fontNames.length);  //获取随机的字体
 47         String fontName = fontNames[index];
 48         int style = r.nextInt(4);         //随机获取字体的样式,0是无样式,1是加粗,2是斜体,3是加粗加斜体
 49         int size = r.nextInt(10) + 24;    //随机获取字体的大小
 50         return new Font(fontName, style, size);   //返回一个随机的字体
 51     }
 52 
 53     /**
 54      * 获取随机字符
 55      *
 56      * @return
 57      */
 58     private char randomChar() {
 59         int index = r.nextInt(codes.length());
 60         return codes.charAt(index);
 61     }
 62 
 63     /**
 64      * 画干扰线,验证码干扰线用来防止计算机解析图片
 65      *
 66      * @param image
 67      */
 68     private void drawLine(BufferedImage image) {
 69         int num = r.nextInt(10); //定义干扰线的数量
 70         Graphics2D g = (Graphics2D) image.getGraphics();
 71         for (int i = 0; i < num; i++) {
 72             int x1 = r.nextInt(weight);
 73             int y1 = r.nextInt(height);
 74             int x2 = r.nextInt(weight);
 75             int y2 = r.nextInt(height);
 76             g.setColor(randomColor());
 77             g.drawLine(x1, y1, x2, y2);
 78         }
 79     }
 80 
 81     /**
 82      * 创建图片的方法
 83      *
 84      * @return
 85      */
 86     private BufferedImage createImage() {
 87         //创建图片缓冲区
 88         BufferedImage image = new BufferedImage(weight, height, BufferedImage.TYPE_INT_RGB);
 89         //获取画笔
 90         Graphics2D g = (Graphics2D) image.getGraphics();
 91         //设置背景色随机
 92         g.setColor(new Color(255, 255, r.nextInt(245) + 10));
 93         g.fillRect(0, 0, weight, height);
 94         //返回一个图片
 95         return image;
 96     }
 97 
 98     /**
 99      * 获取验证码图片的方法
100      *
101      * @return
102      */
103     public BufferedImage getImage() {
104         BufferedImage image = createImage();
105         Graphics2D g = (Graphics2D) image.getGraphics(); //获取画笔
106         StringBuilder sb = new StringBuilder();
107         for (int i = 0; i < 4; i++)             //画四个字符即可
108         {
109             String s = randomChar() + "";      //随机生成字符,因为只有画字符串的方法,没有画字符的方法,所以需要将字符变成字符串再画
110             sb.append(s);                      //添加到StringBuilder里面
111             float x = i * 1.0F * weight / 4;   //定义字符的x坐标
112             g.setFont(randomFont());           //设置字体,随机
113             g.setColor(randomColor());         //设置颜色,随机
114             g.drawString(s, x, height - 5);
115         }
116         this.text = sb.toString();
117         drawLine(image);
118         return image;
119     }
120 
121     /**
122      * 获取验证码文本的方法
123      *
124      * @return
125      */
126     public String getText() {
127         return text;
128     }
129 
130     public static void output(BufferedImage image, OutputStream out) throws IOException                  //将验证码图片写出的方法
131     {
132         ImageIO.write(image, "JPEG", out);
133     }
134 }

2、在控制器中把图片响应给前端页面

 1 @RequestMapping("getVerifiCode")
 2     @ResponseBody
 3     public void getVerifiCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
 4         /*
 5              1.生成验证码
 6              2.把验证码上的文本存在session中
 7              3.把验证码图片发送给客户端
 8              */
 9         ImageVerificationCode ivc = new ImageVerificationCode();     //用我们的验证码类,生成验证码类对象
10         BufferedImage image = ivc.getImage();  //获取验证码
11         request.getSession().setAttribute("text", ivc.getText()); //将验证码的文本存在session中
12         ivc.output(image, response.getOutputStream());//将验证码图片响应给客户端
13     }

3、从session获得验证码字符

1 @RequestMapping("Login_authentication")
2     @ResponseBody
3     public String Login_authentication(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
4         request.setCharacterEncoding("utf-8");
5         String session_vcode=(String) request.getSession().getAttribute("text");    //从session中获取真正的验证码
6         return session_vcode;
7     }

4、前端请求图片

1 <a href="javascript:getVerifiCode()">
2     <img id="yzm_img" style="cursor:pointer;width: 100px;height: 36px;margin: 5px 0 0 5px;border-radius: 3px;" title="点击刷新验证码" src="Mcake/getVerifiCode"/>
3 </a>
4 function getVerifiCode() {
5     $("#yzm_img").prop('src','Mcake/getVerifiCode?a='+new Date().getTime());
6 }

 

转载于:https://www.cnblogs.com/fenghh/p/10154191.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/412576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[css] 怎么让英文单词的首字母大写?

[css] 怎么让英文单词的首字母大写&#xff1f; 楼上用的没问题&#xff0c;学习嘛&#xff0c;那我就来扩展一下。text-transform 属性控制文本的大小写&#xff0c;是CSS2.1的属性&#xff0c;兼容性问题不大。 属性值是关键字&#xff0c;有41种&#xff0c;这个1是实验性属…

Zuul 1.x 升级 springcloud gateway 2.x 遇到的一点问题

大家好&#xff0c;我是烤鸭&#xff1a; 今天分享 Zuul 1.x 升级 springcloud gateway 2.x 遇到的一点问题。 介绍 zuul 和springcloud gateway 都是比较优秀的网关&#xff0c;而 zuul 1.x 采用的是 servlet 模型&#xff0c;gate 采用的是 reactor模型&#xff0c;效率和资…

render_template 网页模板

模板简单介绍&#xff1a; 视图函数&#xff1a;视图函数就是装饰器所装饰的方法&#xff0c;视图函数的主要作用是生成请求的响应&#xff0c;这是最简单的请求。实际上&#xff0c;视图函数有两个作用&#xff1a;处理业务逻辑和返回响应内容。在大型应用中&#xff0c;把业务…

[css] 怎么才能让图文不可复制?

[css] 怎么才能让图文不可复制&#xff1f; -webkit-user-select: none; -ms-user-select: none; -moz-user-select: none; -khtml-user-select: none; user-select: none;个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷…

nacos配置刷新失败导致的cpu上升和频繁重启,nacos配置中心源码解析

大家好&#xff0c;我是烤鸭&#xff1a; nacos 版本 1.3.2&#xff0c;先说下结论&#xff0c;频繁重启的原因确实没有找到&#xff0c;跟nacos有关&#xff0c;日志没有保留多少&#xff0c;只能从源码找下头绪(出问题的版本 server用的是 nacos 1.1&#xff0c;nacos-client…

nova— 计算服务

一、nova介绍&#xff1a; Nova 是 OpenStack 最核心的服务&#xff0c;负责维护和管理云环境的计算资源。OpenStack 作为 IaaS 的云操作系统&#xff0c;虚拟机生命周期管理也就是通过 Nova 来实现的。用途与功能 :1) 实例生命周期管理2) 管理计算资源3) 网络和认证管理4)REST…

[css] 写出你知道的CSS水平和垂直居中的方法

[css] 写出你知道的CSS水平和垂直居中的方法 flex布局水平垂直居中:<!-- html --> <div class"outer"><div class"inner"></div> </div>/*css*/ .outer{display:flex;width:200px;height:200px;border:1px solid red; } .…

springcloud gateway 自定义 accesslog elk

大家好&#xff0c;我是烤鸭&#xff1a; ​ 最近用 springcloud gateway 时&#xff0c;想使用类似 logback-access的功能&#xff0c;用来做数据统计和图表绘制等等&#xff0c;发现没有类似的功能&#xff0c;只能自己开发了。 环境&#xff1a; <dependency><gr…

第二阶段团队绩效考核报告

团队绩效考核 基于各种客观问题本次绩效考核采用和第一次冲刺不一样的标准&#xff0c;根据团队贡献事实打分如下 组员打分&#xff1a; 郭良 &#xff08;9.0&#xff09; 赵承龙 &#xff08;5.5&#xff09; &#xff08;根据组内之前定下的打分细则和本期冲刺过程的事实…

[css] 实现单行文本居中和多行文本左对齐并超出显示“...“

[css] 实现单行文本居中和多行文本左对齐并超出显示"…" .one {text-align: center }.multi {overflow: hiddentext-overflow: ellipsisdisplay: -webkit-box-webkit-line-clamp: 3-webkit-box-orient: vertical }可惜多行文本省略, 有严重的兼容性问题个人简介 我…

jenkins发布docker项目 harbor

大家好&#xff0c;我是烤鸭&#xff1a; ​ jenkins 部署k8s 项目还是比较流畅的&#xff0c;本身建立多流水线项目&#xff0c;在项目中添加jenkinsfile就好了&#xff0c;镜像需要额外的参数&#xff0c;还可以添加dokcerfile文件。由于我现在的问题是不能够修改原有的项…

[css] 不使用border画出1px高的线,在不同浏览器的标准和怪异模式下都能保持效果一样

[css] 不使用border画出1px高的线&#xff0c;在不同浏览器的标准和怪异模式下都能保持效果一样 <div style"width: 100%;height: 1px;"></div><hr size"1">个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&am…

bzoj 3173 最长上升子序列

Written with StackEdit. Description 给定一个序列&#xff0c;初始为空。现在我们将\(1\)到\(N\)的数字插入到序列中&#xff0c;每次将一个数字插入到一个特定的位置。每插入一个数字&#xff0c;我们都想知道此时最长上升子序列长度是多少&#xff1f; Input 第一行一个整数…

java 调用linux 脚本并获取返回值

大家好&#xff0c;我是烤鸭&#xff1a; 今天分享下java 调用 shell脚本 并获取返回值。 代码实践 String cmd "df -h"; StringBuffer sb new StringBuffer(); Process process Runtime.getRuntime().exec(cmd); BufferedReader br new BufferedReader(new In…

[css] 写出主流浏览器内核私有属性的css前缀

[css] 写出主流浏览器内核私有属性的css前缀 完善一下&#xff1a; Chrome&#xff1a;Blink内核 -webkit-Safari&#xff1a;WebKit内核 -webkit-Firefox &#xff1a;Gecko内核 -moz-IE&#xff1a;Trident内核 -ms-Opera&#xff1a;Presto内核 …

补充小知识:文件句柄与文件标识符

#文件句柄 这是操作系统里的一个概念&#xff0c;句柄是WINDOWS用来标识被应用程序所建立或使用的对象的唯一整数&#xff0c;WINDOWS使用各种各样的句柄标识诸如应用程序实例&#xff0c;窗口&#xff0c;控制&#xff0c;位图&#xff0c;GDI对象等等。WINDOWS句柄有点象C语言…

[css] 使用flex实现三栏布局,两边固定,中间自适应

[css] 使用flex实现三栏布局&#xff0c;两边固定&#xff0c;中间自适应 同意里面的一个回答&#xff0c;现在有很多简单的实现方式&#xff0c;传统的这个也是一种hack的方式&#xff0c;真的没必要去追究了&#xff0c;但是核心知识点可以掌握。1.把 center 放在最前面&…

saltstack部署java应用失败无日志——CICD 部署

大家好&#xff0c;我是烤鸭&#xff1a; ​   最近在搞公司的CICD&#xff0c;遇到各种问题。复盘总结一下。 CICD 架构 这篇文章写得很详细&#xff0c;可以看一下 https://linux.cn/article-9926-1.html 而这里只是结合现在的情况分析下&#xff1a; CI 持续集成&…

day15 webUI自动化

一、webdriver的原理 driver webdriver.Chrome()创建浏览器&#xff0c;当做我们的服务端&#xff0c;代码就是客户端&#xff0c;和客户端进行ip绑定&#xff0c;基于http协议发送post请求 WebDriver webdriver是按照server – client的经典设计模式设计的。 webdriver的作用…

[css] 浏览器是怎样判断元素是否和某个CSS选择器匹配?

[css] 浏览器是怎样判断元素是否和某个CSS选择器匹配&#xff1f; 有选择器&#xff1a; div.ready #wrapper > .bg-red 先把所有元素 class 中有 bg-red 的元素拿出来组成一个集合&#xff0c;然后上一层&#xff0c;对每一个集合中的元素&#xff0c;如果元素的 parent i…