diff --git a/xs-service/src/main/java/com/xiang/xservice/auth/service/enums/CaptchaTypeEnum.java b/xs-service/src/main/java/com/xiang/xservice/auth/service/enums/CaptchaTypeEnum.java new file mode 100644 index 0000000..40334a5 --- /dev/null +++ b/xs-service/src/main/java/com/xiang/xservice/auth/service/enums/CaptchaTypeEnum.java @@ -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; +} diff --git a/xs-service/src/main/java/com/xiang/xservice/auth/service/service/CaptchaGenerateFactory.java b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/CaptchaGenerateFactory.java new file mode 100644 index 0000000..9bec7bb --- /dev/null +++ b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/CaptchaGenerateFactory.java @@ -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 strategies = Maps.newConcurrentMap(); + + public CaptchaGenerateFactory(List 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); + } +} diff --git a/xs-service/src/main/java/com/xiang/xservice/auth/service/service/ICaptchaService.java b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/ICaptchaService.java new file mode 100644 index 0000000..b9e10fa --- /dev/null +++ b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/ICaptchaService.java @@ -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(); +} diff --git a/xs-service/src/main/java/com/xiang/xservice/auth/service/service/impl/captcha/NormalCaptchaImage.java b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/impl/captcha/NormalCaptchaImage.java new file mode 100644 index 0000000..8b0c045 --- /dev/null +++ b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/impl/captcha/NormalCaptchaImage.java @@ -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; + } + +} diff --git a/xs-service/src/main/resources/mapper/user/XUserMapper.xml b/xs-service/src/main/resources/mapper/user/XUserMapper.xml index 2cb5254..9f7feb2 100644 --- a/xs-service/src/main/resources/mapper/user/XUserMapper.xml +++ b/xs-service/src/main/resources/mapper/user/XUserMapper.xml @@ -19,6 +19,7 @@ + @@ -36,7 +37,8 @@ create_by, create_time, update_by, - update_time + update_time, + tenant_id @@ -82,7 +84,10 @@ update_by, - update_time + update_time, + + + tenant_id @@ -126,14 +131,17 @@ #{updateBy}, - #{updateTime} + #{updateTime}, + + + #{tenantId} - insert into x_user(name, username, password, email, phone, status) VALUES + insert into x_user(name, username, password, email, phone, status, tenant_id) VALUES - (#{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}) @@ -156,7 +164,8 @@ create_by = #{createBy}, create_time = #{createTime}, update_by = #{updateBy}, - update_time = #{updateTime} + update_time = #{updateTime}, + tenant_id = #{tenantId} WHERE id = #{id}