⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/2301_79728896 「青风未央」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

这是一个登录页面,在登录的最后一步,很多时候都会让我们输入验证码,今天就来讲讲如何在SpringBoot中实现图形验证码的生成。验证码的生成是一个非常常用的工具类,网上有很多写法。

手写验证码

首先说明一下,这里的手写,并不是博主自己手写的,而是在GitHub中看到过一个项目,项目中有涉及到一个验证码的源码,感觉还不错。

新建验证码工具类

验证码工具类

public class Code{    publicstaticfinal String RANDOMCODEKEY = "ValidateCode";    //将图片存放到Session中的key    private Random random = new Random();//生成随机数    private String randomString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";    //图片中随机产生的字母或数字    privateint width = 80;//图片宽    privateint height = 26;//图片高    privateint lineSize = 40;//干扰线数量    privateint stringNum = 4;//随机产生字符数量    //获得字体    private Font getFont(){        returnnew Font("Fixedsys",Font.CENTER_BASELINE,18);    }    //获得随机颜色值    private Color getRandColor(int fc,int bc){        if(fc > 255) {            fc = 255;        }        if(bc > 255) {            bc = 255;        }        int r = fc + random.nextInt(bc-fc-16);        int g = fc + random.nextInt(bc-fc-14);        int b = fc + random.nextInt(bc-fc-18);        returnnew Color(r,g,b);    }    /*
* 返回随机的字符
*/ private String getRandomString(int num){ return String.valueOf(randomString.charAt(num)); } /*
* 绘制字符串
*/ private String drawString(Graphics g, String randomString, int i){ g.setFont(getFont()); g.setColor(new Color(random.nextInt(101),random.nextInt(111),random.nextInt(121))); String rand = String.valueOf(getRandomString(random.nextInt(this.randomString.length()))); randomString += rand; g.translate(random.nextInt(3), random.nextInt(3)); g.drawString(rand, 13 * i, 16); return randomString; } /*
* 绘制干扰线
*/ privatevoiddrawLine(Graphics g){ int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(13); int yl = random.nextInt(15); g.drawLine(x, y, x + xl, y + yl); } //核心方法:生成随机验证码,并返回 publicvoidgetValidateCode(HttpServletRequest request, HttpServletResponse response){ HttpSession session = request.getSession(); BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR); Graphics g = image.getGraphics();//产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作 g.fillRect(0, 0, width, height); g.setFont(new Font("Times New Roman",Font.ROMAN_BASELINE,18)); g.setColor(getRandColor(110, 133)); //绘制干扰线 for(int i = 0;i <= lineSize; i++){ drawLine(g); } //绘制随机字符 String randomString = ""; for(int i = 1; i <= stringNum; i++){ randomString = drawString(g, randomString, i); } //将生成的随机字符串装进Session作用域 session.removeAttribute(RANDOMCODEKEY); session.setAttribute(RANDOMCODEKEY, randomString); System.out.println(randomString);//输出生成的随机字符串 g.dispose();//关闭窗体,释放资源 try { ImageIO.write(image, "JPEG", response.getOutputStream());//将内存中的图片通过流动形式输出到客户端 } catch (Exception e) { e.printStackTrace(); } }}

在SpringBoot项目中新建一个util包,用于存放工具类,这样一个验证码工具类就写好了。

Controller中调用

工具类写好后,就可以在Controller中调用

@GetMapping("/checkCode2")
public void checkcode2(HttpServletRequest request, HttpServletResponse response){
response.setContentType("image/jpeg");
response.setDateHeader("Expires",0);
response.setHeader("Pragma","no-cache");
response.setHeader("Cache-Control","no-cache");
//引用验证码工具类,生成验证码
Code code=new Code();
code.getValidateCode(request,response);
}
  • @GetMapping("/checkCode2"): 这是一个Spring MVC注解,表示当客户端发送一个GET请求到/checkCode2路径时,将调用checkcode2方法。
  • public void checkcode2(HttpServletRequest request, HttpServletResponse response): 这是一个控制器方法,接收HttpServletRequest和HttpServletResponse对象作为参数,用于处理HTTP请求和响应。
  • response.setContentType("image/jpeg");: 设置响应的内容类型为JPEG格式的图片。
  • response.setDateHeader("Expires",0);: 设置响应头Expires为0,表示页面内容已过期,浏览器应当每次都从服务器获取最新内容。
  • response.setHeader("Pragma","no-cache");: 设置响应头Pragma为no-cache,指示浏览器不要缓存页面内容。
  • response.setHeader("Cache-Control","no-cache");: 设置响应头Cache-Control为no-cache,进一步指示浏览器不要缓存页面内容。
  • Code code=new Code();: 创建一个Code类的实例。
  • code.getValidateCode(request,response);: 调用Code实例的getValidateCode方法,生成验证码并将其写入响应中。

Apifox中验证

Hutool图形验证码

Hutool官网:

> https://www.hutool.cn/docs/#/
>

正如官网简介所言,Hutool是一个小而全的Java工具类库,它提供了很多常用的工具类,几乎包罗万象。

今天我们使用的是hutool-captcha(图形验证码)。

引入依赖

这里使用的是Maven,如果是其他的项目构建工具,请参考文档。

单独引入图形验证码的依赖模块

<!-- 添加图形验证码依赖 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
<version>5.8.6</version>
</dependency>

当然,为了方便,也可以按照文档中的方法,引入所有模块。

<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>

LineCaptcha:线段干扰的验证码

@GetMapping("/checkCode1")
public void checkCode(HttpServletResponse response) throws IOException { //调用Hutool的图形验证码 LineCaptcha captcha = CaptchaUtil.createLineCaptcha(130, 38, 5, 5); //指示浏览器不要缓存页面内容 response.setHeader("Pragma","no-cache"); //进一步指示浏览器不要缓存页面内容 response.setHeader("Cache-Control","no-cache"); //表示页面内容已过期,浏览器应当每次都从服务器获取最新内容 response.setDateHeader("Expires",0); //表示返回的内容为JPEG格式的图片 response.setContentType("image/jpeg"); //图片验证码写出 captcha.write(response.getOutputStream()); //关闭流 response.getOutputStream().close();}
  • LineCaptcha captcha = CaptchaUtil.createLineCaptcha(130, 38, 5, 5): 定义图形验证码的长、宽、验证码字符数、干扰线宽度
  • LineCaptcha captcha = CaptchaUtil.createLineCaptcha(130, 38): 定义图形验证码的长、宽

上面这两种写法都是可以的

CircleCaptcha:圆形干扰验证码

@GetMapping("/checkCode1")publicvoidcheckCode(HttpServletResponse response)throws IOException {    //调用Hutool的图形验证码    CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(130, 38, 5, 20);    //指示浏览器不要缓存页面内容    response.setHeader("Pragma","no-cache");    //进一步指示浏览器不要缓存页面内容    response.setHeader("Cache-Control","no-cache");    //表示页面内容已过期,浏览器应当每次都从服务器获取最新内容    response.setDateHeader("Expires",0);    //表示返回的内容为JPEG格式的图片    response.setContentType("image/jpeg");    //图片验证码写出    captcha.write(response.getOutputStream());    //关闭流    response.getOutputStream().close();}
  • CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(130, 38, 5, 20): 定义图形验证码的长、宽、验证码字符数、干扰⭕个数
  • CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(130, 38): 定义图形验证码的长、宽

圆形干扰验证码同样两种写法。

ShearCaptcha:扭曲干扰验证码

@GetMapping("/checkCode1")publicvoidcheckCode(HttpServletResponse response)throws IOException {    //调用Hutool的图形验证码    ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(130, 38,5,5);    //指示浏览器不要缓存页面内容    response.setHeader("Pragma","no-cache");    //进一步指示浏览器不要缓存页面内容    response.setHeader("Cache-Control","no-cache");    //表示页面内容已过期,浏览器应当每次都从服务器获取最新内容    response.setDateHeader("Expires",0);    //表示返回的内容为JPEG格式的图片    response.setContentType("image/jpeg");    //图片验证码写出    captcha.write(response.getOutputStream());    //关闭流    response.getOutputStream().close();}
  • ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(130, 38,5,5):定义图形验证码的长、宽、验证码字符数、干扰线宽度
  • ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(130, 38):定义图形验证码的长、宽

GifCaptcha:GIF验证码

@GetMapping("/checkCode1")publicvoidcheckCode(HttpServletResponse response)throws IOException {    //调用Hutool的图形验证码    GifCaptcha captcha = CaptchaUtil.createGifCaptcha(130, 38,5);    //指示浏览器不要缓存页面内容    response.setHeader("Pragma","no-cache");    //进一步指示浏览器不要缓存页面内容    response.setHeader("Cache-Control","no-cache");    //表示页面内容已过期,浏览器应当每次都从服务器获取最新内容    response.setDateHeader("Expires",0);    //表示返回的内容为JPEG格式的图片    response.setContentType("image/jpeg");    //图片验证码写出    captcha.write(response.getOutputStream());    //关闭流    response.getOutputStream().close();}
  • GifCaptcha captcha = CaptchaUtil.createGifCaptcha(130, 38,5):定义GIF验证码的长、宽、验证码字符数
  • GifCaptcha captcha = CaptchaUtil.createGifCaptcha(130, 38):定义GIF验证码的长、宽

大家可以去试试,这里截不出那种Gif的效果

自定义验证码

纯数字验证码

@GetMapping("/checkCode1")publicvoidcheckCode(HttpServletResponse response)throws IOException {    // 自定义纯数字的验证码(随机4位数字,可重复)    RandomGenerator randomGenerator = new RandomGenerator("0123456789", 4);    LineCaptcha captcha = CaptchaUtil.createLineCaptcha(200, 100);    captcha.setGenerator(randomGenerator);    // 重新生成code    captcha.createCode();    //指示浏览器不要缓存页面内容    response.setHeader("Pragma","no-cache");    //进一步指示浏览器不要缓存页面内容    response.setHeader("Cache-Control","no-cache");    //表示页面内容已过期,浏览器应当每次都从服务器获取最新内容    response.setDateHeader("Expires",0);    //表示返回的内容为JPEG格式的图片    response.setContentType("image/jpeg");    //图片验证码写出    captcha.write(response.getOutputStream());    //关闭流    response.getOutputStream().close();}

当然除了LineCaptcha,CircleCaptcha,GifCaptcha,ShearCaptcha都是可以的

纯字母验证码

@GetMapping("/checkCode1")publicvoidcheckCode(HttpServletResponse response)throws IOException {    // 自定义纯数字的验证码(随机4位数字,可重复)    RandomGenerator randomGenerator = new RandomGenerator("abcdefghijklmnopqrstuvwyzx", 4);    CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100);    captcha.setGenerator(randomGenerator);    // 重新生成code    captcha.createCode();    //指示浏览器不要缓存页面内容    response.setHeader("Pragma","no-cache");    //进一步指示浏览器不要缓存页面内容    response.setHeader("Cache-Control","no-cache");    //表示页面内容已过期,浏览器应当每次都从服务器获取最新内容    response.setDateHeader("Expires",0);    //表示返回的内容为JPEG格式的图片    response.setContentType("image/jpeg");    //图片验证码写出    captcha.write(response.getOutputStream());    //关闭流    response.getOutputStream().close();}

四则运算验证码

@GetMapping("/checkCode1")publicvoidcheckCode(HttpServletResponse response)throws IOException {    ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 45, 4, 4);    // 自定义验证码内容为四则运算方式    captcha.setGenerator(new MathGenerator());    // 重新生成code    captcha.createCode();    //指示浏览器不要缓存页面内容    response.setHeader("Pragma","no-cache");    //进一步指示浏览器不要缓存页面内容    response.setHeader("Cache-Control","no-cache");    //表示页面内容已过期,浏览器应当每次都从服务器获取最新内容    response.setDateHeader("Expires",0);    //表示返回的内容为JPEG格式的图片    response.setContentType("image/jpeg");    //图片验证码写出    captcha.write(response.getOutputStream());    //关闭流    response.getOutputStream().close();}

文章目录
  1. 1. 手写验证码
    1. 1.1. 新建验证码工具类
      1. 1.1.1. 验证码工具类
    2. 1.2. Controller中调用
    3. 1.3. Apifox中验证
  2. 2. Hutool图形验证码
    1. 2.1. 引入依赖
    2. 2.2. LineCaptcha:线段干扰的验证码
    3. 2.3. CircleCaptcha:圆形干扰验证码
    4. 2.4. ShearCaptcha:扭曲干扰验证码
    5. 2.5. GifCaptcha:GIF验证码
    6. 2.6. 自定义验证码
      1. 2.6.1. 纯数字验证码
      2. 2.6.2. 纯字母验证码
      3. 2.6.3. 四则运算验证码