• 生成验证码图片


    引入依赖包

    1. <dependency>
    2. <groupId>com.github.pengglegroupId>
    3. <artifactId>kaptchaartifactId>
    4. <version>2.3.2version>
    5. dependency>

     配置DefaultKaptcha类

    类方法配置了验证码的生成格式和规则,并返回一个DefaultKaptcha对象并注入到Spring中

    1. package com.dream.datacenter.config;
    2. import com.google.code.kaptcha.impl.DefaultKaptcha;
    3. import com.google.code.kaptcha.util.Config;
    4. import org.springframework.context.annotation.Bean;
    5. import org.springframework.stereotype.Component;
    6. import java.util.Properties;
    7. /**
    8. * Created with IntelliJ IDEA
    9. * 图形验证码属性配置
    10. * @Author: Mr.HPC
    11. * @Date: 2022/1/6 23:08
    12. * @Version 1.0
    13. */
    14. @Component
    15. public class CodeImgConfig {
    16. @Bean
    17. public DefaultKaptcha getDefaultKaptcha() {
    18. DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
    19. Properties properties = new Properties();
    20. // 图片边框
    21. properties.setProperty("kaptcha.border", "no");
    22. // 边框颜色
    23. properties.setProperty("kaptcha.border.color", "black");
    24. //边框厚度
    25. properties.setProperty("kaptcha.border.thickness", "1");
    26. // 图片宽
    27. properties.setProperty("kaptcha.image.width", "200");
    28. // 图片高
    29. properties.setProperty("kaptcha.image.height", "50");
    30. //图片实现类
    31. properties.setProperty("kaptcha.producer.impl", "com.google.code.kaptcha.impl.DefaultKaptcha");
    32. //文本实现类
    33. properties.setProperty("kaptcha.textproducer.impl", "com.google.code.kaptcha.text.impl.DefaultTextCreator");
    34. //文本集合,验证码值从此集合中获取
    35. properties.setProperty("kaptcha.textproducer.char.string", "01234567890");
    36. //验证码长度
    37. properties.setProperty("kaptcha.textproducer.char.length", "4");
    38. //字体
    39. properties.setProperty("kaptcha.textproducer.font.names", "宋体");
    40. //字体颜色
    41. properties.setProperty("kaptcha.textproducer.font.color", "black");
    42. //文字间隔
    43. properties.setProperty("kaptcha.textproducer.char.space", "5");
    44. //干扰实现类
    45. properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.DefaultNoise");
    46. //干扰颜色
    47. properties.setProperty("kaptcha.noise.color", "blue");
    48. //干扰图片样式
    49. properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.WaterRipple");
    50. //背景实现类
    51. properties.setProperty("kaptcha.background.impl", "com.google.code.kaptcha.impl.DefaultBackground");
    52. //背景颜色渐变,结束颜色
    53. properties.setProperty("kaptcha.background.clear.to", "white");
    54. //文字渲染器
    55. properties.setProperty("kaptcha.word.impl", "com.google.code.kaptcha.text.impl.DefaultWordRenderer");
    56. Config config = new Config(properties);
    57. defaultKaptcha.setConfig(config);
    58. return defaultKaptcha;
    59. }
    60. }

    Controller 请求方法

    1. package com.dream.datacenter.controller;
    2. import com.dream.datacenter.shiro.JWTUtil;
    3. import com.dream.datacenter.utils.ImageUtil;
    4. import com.google.code.kaptcha.impl.DefaultKaptcha;
    5. import io.jsonwebtoken.Claims;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.data.redis.core.RedisTemplate;
    8. import org.springframework.web.bind.annotation.RequestMapping;
    9. import org.springframework.web.bind.annotation.RestController;
    10. import javax.annotation.Resource;
    11. import javax.servlet.http.HttpServletRequest;
    12. import javax.servlet.http.HttpServletResponse;
    13. import java.util.HashMap;
    14. import java.util.concurrent.TimeUnit;
    15. @RestController
    16. @RequestMapping("/test")
    17. public class testController {
    18. public static final String VERIFICATION_CODE = "verificationCode_";
    19. @Autowired
    20. public RedisTemplate redisTemplate;
    21. @Resource
    22. private DefaultKaptcha captcha;
    23. /**
    24. * 第一种方式
    25. * 使用DefaultKaptcha生成登录验证码图片
    26. * 转成base64编码的字符串输出到前端
    27. * 实际项目这里还要加入JWT令牌校验和redis缓存
    28. */
    29. @RequestMapping(value = {"/loginValidateCode"})
    30. public String loginValidateCode(HttpServletRequest request, HttpServletResponse response) throws Exception{
    31. response.setDateHeader("Expires", 0);
    32. // Set standard HTTP/1.1 no-cache headers.
    33. response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
    34. // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
    35. response.addHeader("Cache-Control", "post-check=0, pre-check=0");
    36. // Set standard HTTP/1.0 no-cache header.
    37. response.setHeader("Pragma", "no-cache");
    38. // return a jpeg
    39. response.setContentType("image/jpeg");
    40. // 生成图片验证码内容
    41. String capText = captcha.createText();
    42. // 获取用户的jwt令牌
    43. String userVerificationJwt = request.getHeader(JWTUtil.JWT_VERIFICATION_KEY);
    44. //验证码令牌
    45. Claims claims = JWTUtil.validateJwtToken(userVerificationJwt);
    46. if(claims == null){
    47. //如果用户令牌过期那么对应存放在redis中的数据也要清空
    48. if(!org.apache.commons.lang3.StringUtils.isEmpty(userVerificationJwt)){
    49. redisTemplate.expire(VERIFICATION_CODE + userVerificationJwt, 1, TimeUnit.DAYS);
    50. }
    51. //重新生成用户令牌
    52. userVerificationJwt = JWTUtil.createJwt(new HashMap() ,JWTUtil.EXPIRE_TIME);
    53. //将jwt令牌放入 response head中
    54. response.setHeader(JWTUtil.JWT_VERIFICATION_KEY, userVerificationJwt);
    55. }
    56. //刷新缓存,更新验证码
    57. redisTemplate.opsForValue().set(VERIFICATION_CODE + userVerificationJwt , capText,60, TimeUnit.SECONDS);
    58. System.out.println(capText);
    59. // ImageUtil.validateCode(response,captcha,capText);
    60. //生成图片
    61. String code = "data:image/png;base64," + ImageUtil.validateCode(captcha,capText);
    62. return code;
    63. }
    64. /**
    65. * 第二种方式
    66. * 使用Graphics绘图来定制格式,生成验证码
    67. * 转成base64编码的字符串输出到前端
    68. */
    69. @RequestMapping(value = {"/loginValidateCode1"})
    70. public String loginValidateCode1(HttpServletRequest request, HttpServletResponse response) throws Exception{
    71. response.setDateHeader("Expires", 0);
    72. // Set standard HTTP/1.1 no-cache headers.
    73. response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
    74. // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
    75. response.addHeader("Cache-Control", "post-check=0, pre-check=0");
    76. // Set standard HTTP/1.0 no-cache header.
    77. response.setHeader("Pragma", "no-cache");
    78. // return a jpeg
    79. response.setContentType("image/png");
    80. String str = captcha.createText();//使用DefaultKaptcha规则生成随机码
    81. //生成图片
    82. String code = "data:image/png;base64," + ImageUtil.createImageWithVerifyCode(str,200,50);
    83. return code;
    84. }
    85. /**
    86. * 第三种方式
    87. * 使用DefaultKaptcha生成登录验证码图片
    88. * 并用文件流方式输出到前端
    89. */
    90. @RequestMapping(value = {"/loginValidateCode2"})
    91. public void loginValidateCode2(HttpServletRequest request, HttpServletResponse response) throws Exception{
    92. response.setDateHeader("Expires", 0);
    93. // Set standard HTTP/1.1 no-cache headers.
    94. response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
    95. // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
    96. response.addHeader("Cache-Control", "post-check=0, pre-check=0");
    97. // Set standard HTTP/1.0 no-cache header.
    98. response.setHeader("Pragma", "no-cache");
    99. // return a jpeg
    100. response.setContentType("image/png");
    101. ImageUtil.validateCode(response,captcha,captcha.createText());
    102. }
    103. }

     ImageUtil公共类

    1. package com.dream.datacenter.utils;
    2. import com.google.code.kaptcha.impl.DefaultKaptcha;
    3. import java.util.Base64;
    4. import java.util.Base64.Encoder;
    5. import javax.imageio.ImageIO;
    6. import javax.servlet.ServletOutputStream;
    7. import javax.servlet.http.HttpServletResponse;
    8. import java.awt.*;
    9. import java.awt.image.BufferedImage;
    10. import java.io.ByteArrayOutputStream;
    11. import java.io.IOException;
    12. import java.util.Random;
    13. /**
    14. * Created with IntelliJ IDEA
    15. *
    16. * @Author: Mr.HPC
    17. * @Date: 2022/1/6 23:19
    18. * @Version 1.0
    19. * 验证码工具类
    20. */
    21. public class ImageUtil {
    22. /**
    23. * 第一种,用于IO输出
    24. * @param captchaProducer 生成图片方法类
    25. * @throws Exception
    26. */
    27. public static void validateCode(HttpServletResponse response,
    28. DefaultKaptcha captchaProducer,String capText) throws Exception{
    29. // create the image with the text
    30. BufferedImage bi = captchaProducer.createImage(capText);
    31. ServletOutputStream out = response.getOutputStream();
    32. // write the data out
    33. ImageIO.write(bi, "JPEG", out);
    34. try {
    35. out.flush();
    36. } finally {
    37. out.close();
    38. }
    39. }
    40. /**
    41. * 第二种
    42. * 生成验证码图片转 base64,用于方法请求后,将结果赋值到img标签src属性
    43. * @param captchaProducer 生成图片方法类
    44. * @throws Exception
    45. */
    46. public static String validateCode(DefaultKaptcha captchaProducer,String capText) throws Exception{
    47. // create the image with the text
    48. BufferedImage bi = captchaProducer.createImage(capText);
    49. return returnPicBase64(bi);
    50. }
    51. /**
    52. * 第三种,生成验证码图片转 base64,用于方法请求后,将结果赋值到img标签src属性
    53. * @param word 要生存的验证码随机字符串
    54. * @param width 图片宽度
    55. * @param height 图片高度
    56. * @return base64 格式生成的验证码图片
    57. * @throws IOException
    58. */
    59. public static String createImageWithVerifyCode(String word, int width, int height) throws IOException {
    60. String png_base64="";
    61. //绘制内存中的图片
    62. BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
    63. //得到画图对象
    64. Graphics graphics = bufferedImage.getGraphics();
    65. //绘制图片前指定一个颜色
    66. graphics.setColor(getRandColor(160,200));
    67. graphics.fillRect(0,0,width,height);
    68. //绘制边框
    69. graphics.setColor(Color.white);
    70. graphics.drawRect(0, 0, width - 1, height - 1);
    71. // 步骤四 四个随机数字
    72. Graphics2D graphics2d = (Graphics2D) graphics;
    73. graphics2d.setFont(new Font("宋体", Font.BOLD, 18));
    74. Random random = new Random();
    75. // 定义x坐标
    76. int x = 10;
    77. for (int i = 0; i < word.length(); i++) {
    78. // 随机颜色
    79. graphics2d.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
    80. // 旋转 -30 --- 30度
    81. int jiaodu = random.nextInt(60) - 30;
    82. // 换算弧度
    83. double theta = jiaodu * Math.PI / 180;
    84. // 获得字母数字
    85. char c = word.charAt(i);
    86. //将c 输出到图片
    87. graphics2d.rotate(theta, x, 20);
    88. graphics2d.drawString(String.valueOf(c), x, 20);
    89. graphics2d.rotate(-theta, x, 20);
    90. x += 30;
    91. }
    92. // 绘制干扰线
    93. graphics.setColor(getRandColor(160, 200));
    94. int x1;
    95. int x2;
    96. int y1;
    97. int y2;
    98. for (int i = 0; i < 30; i++) {
    99. x1 = random.nextInt(width);
    100. x2 = random.nextInt(12);
    101. y1 = random.nextInt(height);
    102. y2 = random.nextInt(12);
    103. graphics.drawLine(x1, y1, x1 + x2, x2 + y2);
    104. }
    105. graphics.dispose();// 释放资源
    106. return returnPicBase64(bufferedImage);
    107. }
    108. /**
    109. * 将图片字节数组码转为base64编码
    110. * @param bi
    111. * @return
    112. * @throws IOException
    113. */
    114. private static String returnPicBase64(BufferedImage bi) throws IOException {
    115. String png_base64;
    116. ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
    117. ImageIO.write(bi, "png", baos);//写入流中
    118. byte[] bytes = baos.toByteArray();//转换成字节
    119. // BASE64Encoder encoder = new BASE64Encoder();
    120. // png_base64 = encoder.encodeBuffer(bytes).trim();
    121. Encoder encoder = Base64.getEncoder();
    122. png_base64 = encoder.encodeToString(bytes).trim();
    123. png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
    124. return png_base64;
    125. }
    126. /**设置随机颜色*/
    127. private static Color getRandColor(int fc, int bc) {
    128. // 取其随机颜色
    129. Random random = new Random();
    130. if (fc > 255) {
    131. fc = 255;
    132. }
    133. if (bc > 255) {
    134. bc = 255;
    135. }
    136. int r = fc + random.nextInt(bc - fc);
    137. int g = fc + random.nextInt(bc - fc);
    138. int b = fc + random.nextInt(bc - fc);
    139. return new Color(r, g, b);
    140. }
    141. }

    前端代码的调用

    test.js 文件

    1. // 图形校验码接口
    2. export const codeImgUrl = "/api/test/loginValidateCode";
    3. export const codeImgUrl1 = "/api/test/loginValidateCode1";
    4. export const codeImgUrl2 = "/api/test/loginValidateCode2";

    yzm.vue 文件,其中 refreshCode2() 方法的 this.ruleForm.codeimg2 = window.URL.createObjectURL(blob); 是将图片io流转成浏览器可以识别的URL

    1. <template>
    2. <div class="login-wrap">
    3. <el-form label-position="left" :model="ruleForm" :rules="rules" ref="ruleForm" label-width="0px" class="demo-ruleForm login-container">
    4. <el-row>
    5. <el-col :span="4" class="code-box">
    6. <el-text>生成验证码图片转 base64,用于方法请求后,将结果赋值到img标签src属性el-text>
    7. <img :src="ruleForm.codeimg" alt="验证码" class="codeimg" @click="refreshCode()">
    8. el-col>
    9. <el-col :span="4" class="code-box">
    10. <el-text>生成验证码图片转 base64,用于方法请求后,将结果赋值到img标签src属性el-text>
    11. <img :src="ruleForm.codeimg1" alt="验证码" class="codeimg" @click="refreshCode1()">
    12. el-col>
    13. <el-col :span="4" class="code-box">
    14. <el-text>生成验证码图片转 base64,用于方法请求后,将结果赋值到img标签src属性el-text>
    15. <img :src="ruleForm.codeimg2" alt="验证码" class="codeimg" @click="refreshCode2()">
    16. el-col>
    17. el-row>
    18. el-form>
    19. div>
    20. template>
    21. <script type="text/ecmascript-6">
    22. import { codeImgUrl,codeImgUrl1,codeImgUrl2 } from '../../api/test';
    23. import md5 from 'js-md5';
    24. import axios from 'axios';
    25. export default {
    26. name: 'yzm',
    27. data() {
    28. return {
    29. ruleForm: {
    30. code: '',
    31. codeimg: '',
    32. codeimg1: '',
    33. codeimg2: ''
    34. },
    35. //rules前端验证
    36. rules: {
    37. }
    38. }
    39. },
    40. // 创建完毕状态(里面是操作)
    41. created() {
    42. // 获取图形验证码
    43. this.refreshCode()
    44. this.refreshCode1()
    45. this.refreshCode2()
    46. },
    47. methods: {
    48. //获取图形验证码
    49. refreshCode() {
    50. // this.ruleForm.codeimg = codeImgUrl+"?t="+Date.now();
    51. let url = codeImgUrl+"?t="+Date.now();
    52. axios.get(url).then(res => {
    53. this.ruleForm.codeimg = res.data
    54. }).catch(resp => {
    55. console.log(resp);
    56. });
    57. },
    58. refreshCode1() {
    59. // this.ruleForm.codeimg = codeImgUrl+"?t="+Date.now();
    60. let url = codeImgUrl1+"?t="+Date.now();
    61. axios.get(url).then(res => {
    62. this.ruleForm.codeimg1 = res.data
    63. }).catch(resp => {
    64. console.log(resp);
    65. });
    66. },
    67. refreshCode2() {
    68. // this.ruleForm.codeimg = codeImgUrl+"?t="+Date.now();
    69. let url = codeImgUrl2+"?t="+Date.now();
    70. axios.request({
    71. url: url,
    72. responseType: 'blob',
    73. method: 'get'
    74. }).then(res => {
    75. let blob = new Blob([res.data], {
    76. type: "image/png"
    77. });
    78. this.ruleForm.codeimg2 = window.URL.createObjectURL(blob);
    79. }), (error) => {
    80. this.$message({
    81. type: 'warning',
    82. message: '系统错误,请联系管理员!'
    83. });
    84. }
    85. },
    86. }
    87. }
    88. script>
    89. <style scoped>
    90. style>

  • 相关阅读:
    Linux常用命令 - 网络管理与通信命令
    Python有向图从起点到终点遍历所有路径
    C语言基础篇 —— 3-2 一文秒懂函数指针
    什么是子网掩码?
    如何给照片添加水印?请看下面3个简单教程
    链式队列----数据结构
    IM即时通讯开发之Android内存泄漏监控
    基于SpringBoot实现自动装配返回属性
    30-Openwrt config save and restore
    VB.net实战(VSTO):Excel插件设计Ribbon界面
  • 原文地址:https://blog.csdn.net/weixin_35654814/article/details/136636608