Skip to content

9、登录时图形验证码服务集成

https://doc.hutool.cn/pages/captcha/

1、验证码生成

  • 验证码-图片内容生成 存MinIO

  • 验证码-数字内容生成 存Redis

2、Redis 配置

yaml
# ========================Redis 配置=====================
---
spring:
  data:
    redis:
      database: 0
      host: 127.0.0.1  # Redis 主机
      password: 123456  # Redis 密码
      port: 6379  # Redis 端口
      timeout: 1s  # Redis 连接超时

3、RedisConfig

java
package com.xx.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @auther xx
 * @create 2024-03-13 11:51
 */
@Configuration
@Slf4j
public class RedisConfig {
    /**
     * redis序列化的工具配置类,下面这个请一定开启配置
     * 127.0.0.1:6379> keys *
     * 1) "ord:102"  序列化过
     * 2) "\xac\xed\x00\x05t\x00\aord:102"   野生,没有序列化过
     * this.redisTemplate.opsForValue(); //提供了操作string类型的所有方法
     * this.redisTemplate.opsForList(); // 提供了操作list类型的所有方法
     * this.redisTemplate.opsForSet(); //提供了操作set的所有方法
     * this.redisTemplate.opsForHash(); //提供了操作hash表的所有方法
     * this.redisTemplate.opsForZSet(); //提供了操作zset的所有方法
     *
     * @param redisConnectionFactor
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactor) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

        redisTemplate.setConnectionFactory(redisConnectionFactor);
        //设置key序列化方式string
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }

}

4、CaptchaController

java
@Test
void createCaptcha() {
    //定义图形验证码的长和宽
    LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
    //图形验证码写出,可以写出到文件,也可以写出到流
    lineCaptcha.write("/Users/xueqimiao/Desktop/pic/captcha.png");
    //输出code
    Console.log(lineCaptcha.getCode());
}
java
package com.xx.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.net.NetUtil;
import com.xx.common.Result;
import com.xx.util.MinIoUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

/**
 * @Author: xueqimiao
 * @Date: 2025/3/5 16:40
 */
@RestController
@RequestMapping("/captcha")
@Slf4j
@Tag(name = "验证码")
public class CaptchaController {

    @Resource
    private MinIoUtil minIoUtil;

    @Resource
    private RedisTemplate redisTemplate;

    @Operation(summary = "生成验证码")
    @GetMapping(value = "/create")
    public Result createCaptcha(HttpServletRequest request) throws IOException {
        String url = "";
        //1 糊涂工具包定义图形验证码的长和宽
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(120, 40);
        //2 上传到minio服务器的文件名
        String fileName = "captcha-" + NetUtil.getLocalMacAddress();
        log.info("=====fileNmae:{}", fileName);
        //3 读取验证码的流式对象
        InputStream inputStream = null;
        try {
            inputStream = new ByteArrayInputStream(lineCaptcha.getImageBytes());
            url = minIoUtil.upload(fileName, inputStream, "image/png");
            // 验证码存储到 Redis,前面的fileName变量就是存入redis的key
            redisTemplate.opsForValue().set(fileName, lineCaptcha.getCode(),60, TimeUnit.SECONDS);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("生成验证码失败");
        } finally {
            inputStream.close();
        }
        return Result.ok(url);
    }
}
image-20250305164749670