feat:验证码(通用数字字母验证码)开发

This commit is contained in:
xiang
2025-09-04 21:23:19 +08:00
parent 199f6b7048
commit 5f3282164f
5 changed files with 191 additions and 6 deletions

View File

@@ -0,0 +1,17 @@
package com.xiang.xservice.auth.service.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum CaptchaTypeEnum {
NORMAL_CAPTCHA_IMAGE(1, "图形验证码"),
;
private final Integer type;
private final String desc;
}

View File

@@ -0,0 +1,28 @@
package com.xiang.xservice.auth.service.service;
import com.google.common.collect.Maps;
import com.xiang.xservice.auth.service.enums.CaptchaTypeEnum;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Component
public class CaptchaGenerateFactory {
private final Map<Integer, ICaptchaService> strategies = Maps.newConcurrentMap();
public CaptchaGenerateFactory(List<ICaptchaService> strategyList) {
for (ICaptchaService captchaService : strategyList) {
strategies.put(captchaService.getCaptchaType().getType(), captchaService);
}
}
public ICaptchaService get(Integer type) {
if (Objects.isNull(type)) {
return strategies.get(CaptchaTypeEnum.NORMAL_CAPTCHA_IMAGE.getType());
}
return strategies.get(type);
}
}

View File

@@ -0,0 +1,10 @@
package com.xiang.xservice.auth.service.service;
import com.xiang.xservice.auth.service.enums.CaptchaTypeEnum;
public interface ICaptchaService {
String getCaptchaImage();
CaptchaTypeEnum getCaptchaType();
}

View File

@@ -0,0 +1,121 @@
package com.xiang.xservice.auth.service.service.impl.captcha;
import com.xiang.xservice.auth.service.enums.CaptchaTypeEnum;
import com.xiang.xservice.auth.service.service.ICaptchaService;
import com.xiang.xservice.basic.utils.RandomCodeUtils;
import com.xiang.xservice.cache.service.IRedisService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.Random;
@Slf4j
@Service
@RequiredArgsConstructor
public class NormalCaptchaImage implements ICaptchaService {
private final IRedisService redisService;
private static final Random random = new Random();
private static final int WIDTH = 160;// 宽
private static final int HEIGHT = 40;// 高
private static final int LINE_SIZE = 30;// 干扰线数量
private static final int STRING_NUMBER = 4;//随机产生字符的个数
@Override
public String getCaptchaImage() {
// BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_BGR);
Graphics g = image.getGraphics();
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(getRandomColor(105, 189));
g.setFont(getFont());
// 绘制干扰线
for (int i = 0; i < LINE_SIZE; i++) {
drawLine(g);
}
String randomCode = "";
// 绘制随机字符
for (int i = 0; i < STRING_NUMBER; i++) {
randomCode = drawString(g, randomCode, i);
}
log.info("生成的随机验证码:{}", randomCode);
g.dispose();
String base64String = "";
//返回 base64
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(image, "PNG", bos);
byte[] bytes = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
base64String = encoder.encodeToString(bytes);
return base64String;
} catch (IOException e) {
log.error("IO异常验证码异常", e);
}
return base64String;
}
@Override
public CaptchaTypeEnum getCaptchaType() {
return CaptchaTypeEnum.NORMAL_CAPTCHA_IMAGE;
}
/**
* 获取字体
*/
private Font getFont() {
return new Font("Times New Roman", Font.PLAIN, 40);
}
/**
* 获取颜色
*/
private static Color getRandomColor(int fc, int bc) {
fc = Math.min(fc, 255);
bc = Math.min(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 - 12);
return new Color(r, g, b);
}
/**
* 绘制干扰线
*/
private void drawLine(Graphics g) {
int x = random.nextInt(WIDTH);
int y = random.nextInt(HEIGHT);
int xl = random.nextInt(20);
int yl = random.nextInt(10);
g.drawLine(x, y, x + xl, y + yl);
}
/**
* 绘制字符串
*/
private String drawString(Graphics g, String randomStr, int i) {
g.setFont(getFont());
g.setColor(getRandomColor(108, 190));
String rand = RandomCodeUtils.getMixtureRandomCode(1);
randomStr += rand;
g.translate(random.nextInt(3), random.nextInt(6));
g.drawString(rand, 40 * i + 10, 25);
return randomStr;
}
}

View File

@@ -19,6 +19,7 @@
<result column="create_time" property="createTime" />
<result column="update_by" property="updateBy" />
<result column="update_time" property="updateTime" />
<result column="tenant_id" property="tenantId"/>
</resultMap>
<sql id="Base_Column_List">
@@ -36,7 +37,8 @@
create_by,
create_time,
update_by,
update_time
update_time,
tenant_id
</sql>
<insert id="insert" useGeneratedKeys="true" keyColumn="id" keyProperty="id" parameterType="com.xiang.xservice.auth.service.entity.XUser">
@@ -82,7 +84,10 @@
update_by,
</if>
<if test="null != updateTime ">
update_time
update_time,
</if>
<if test="tenantId != null">
tenant_id
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
@@ -126,14 +131,17 @@
#{updateBy},
</if>
<if test="null != updateTime ">
#{updateTime}
#{updateTime},
</if>
<if test="tenantId != null">
#{tenantId}
</if>
</trim>
</insert>
<insert id="insertBatch">
insert into x_user(name, username, password, email, phone, status) VALUES
insert into x_user(name, username, password, email, phone, status, tenant_id) VALUES
<foreach collection="list" item="item" separator=",">
(#{item.name}, #{item.username}, #{item.password}, #{item.email}, #{item.phone}, #{item.status})
(#{item.name}, #{item.username}, #{item.password}, #{item.email}, #{item.phone}, #{item.status}, #{item.tenantId})
</foreach>
</insert>
@@ -156,7 +164,8 @@
<if test="null != createBy and '' != createBy">create_by = #{createBy},</if>
<if test="null != createTime ">create_time = #{createTime},</if>
<if test="null != updateBy and '' != updateBy">update_by = #{updateBy},</if>
<if test="null != updateTime ">update_time = #{updateTime}</if>
<if test="null != updateTime ">update_time = #{updateTime},</if>
<if test="null != tenantId ">tenant_id = #{tenantId}</if>
</set>
WHERE id = #{id}
</update>