das项目结构修改

This commit is contained in:
chenhaojie 2024-06-21 17:35:37 +08:00
parent c0f137bb4a
commit 2e0c3a1032
8 changed files with 55 additions and 280 deletions

View File

@ -19,7 +19,6 @@
<java.version>17</java.version>
<maven.plugin.version>3.8.1</maven.plugin.version>
<kaptcha.version>2.3.2</kaptcha.version>
<mybatis.plus.spring.boot>3.5.5</mybatis.plus.spring.boot>
<hutool.version>5.8.25</hutool.version>
@ -78,13 +77,6 @@
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- 验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>

View File

@ -1,104 +0,0 @@
package com.das.common.captcha;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.impl.NoNoise;
import com.google.code.kaptcha.impl.ShadowGimpy;
import com.google.code.kaptcha.util.Config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
import static com.google.code.kaptcha.Constants.*;
/**
* @author chenhaojie
* @Description
*/
@EnableConfigurationProperties({CaptchaProperties.class})
@Configuration
@ConditionalOnProperty(
value = {"captcha.enabled"},
havingValue = "true"
)
public class CaptchaConfiguration {
@ConditionalOnProperty(
value = {"captcha.verify-type"},
havingValue = "random_letter_number"
)
@Bean(name = "captchaProducer")
public DefaultKaptcha getKaptchaBean() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yesno
properties.setProperty(KAPTCHA_BORDER, "yes");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, ShadowGimpy.class.getTypeName());
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
/**
* 默认使用 加减乘除
* @return
*/
@ConditionalOnProperty(
value = {"captcha.verify-type"},
havingValue = "calculate"
)
@Bean(name = "captchaProducerMath")
public DefaultKaptcha getKaptchaBeanMath() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yesno
properties.setProperty(KAPTCHA_BORDER, "yes");
// 边框颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
// 验证码文本生成器
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, CaptchaTextCreator.class.getTypeName());
// 验证码文本字符间距 默认为2
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 验证码噪点颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
// 干扰实现类
properties.setProperty(KAPTCHA_NOISE_IMPL, NoNoise.class.getTypeName());
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, ShadowGimpy.class.getTypeName());
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}

View File

@ -1,59 +0,0 @@
package com.das.common.captcha;
import cn.hutool.core.util.RandomUtil;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
/**
* @author chenhaojie
* @Description 自定义计算结果
*/
public class CaptchaTextCreator extends DefaultTextCreator {
private static final String[] CNUMBERS = new String[]{"0","1","2","3","4","5","6","7","8","9","10"};
@Override
public String getText() {
Integer result = 0;
int x = RandomUtil.randomInt(10);
int y = RandomUtil.randomInt(10);
StringBuilder suChinese = new StringBuilder();
int randomoperands = (int) Math.round(Math.random() * 2);
if (randomoperands == 0) {
result = x * y;
suChinese.append(CNUMBERS[x]);
suChinese.append("*");
suChinese.append(CNUMBERS[y]);
} else if (randomoperands == 1) {
if (!(x == 0) && y % x == 0) {
result = y / x;
suChinese.append(CNUMBERS[y]);
suChinese.append("/");
suChinese.append(CNUMBERS[x]);
} else {
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
} else if (randomoperands == 2) {
if (x >= y) {
result = x - y;
suChinese.append(CNUMBERS[x]);
suChinese.append("-");
suChinese.append(CNUMBERS[y]);
} else {
result = y - x;
suChinese.append(CNUMBERS[y]);
suChinese.append("-");
suChinese.append(CNUMBERS[x]);
}
} else {
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
suChinese.append("=?@" + result);
return suChinese.toString();
}
}

View File

@ -1,77 +0,0 @@
package com.das.common.captcha;
import cn.hutool.core.util.StrUtil;
import com.das.common.constant.AdminConstant;
import com.das.common.exceptions.ServiceException;
import com.das.common.utils.AdminRedisTemplate;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.google.code.kaptcha.Producer;
import org.springframework.util.FastByteArrayOutputStream;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.time.Duration;
import java.util.Base64;
/**
* @author chenhaojie
* @Description
*/
public class CaptchaUtil {
private CaptchaUtil(){}
/**
* 检查验证码是否有效
* @param uuid 唯一键值
* @param codeAnswer 验证码答案
* @param adminRedisTemplate redis工具类
* @return 验证成功为 TRUE 验证失败为 FALSE
*/
public static boolean checkVerificationCode(String uuid, String codeAnswer, AdminRedisTemplate adminRedisTemplate){
String verifyKey = AdminConstant.CAPTCHA_CODE_KEY + uuid;
String answer = adminRedisTemplate.get(verifyKey);
return StrUtil.isNotEmpty(codeAnswer) && answer != null && answer.equals(codeAnswer);
}
/**
* 获取Base64图片
* @param captchaProducerMath 图片生成器
* @param captchaProperties 配置
* @param uuid 唯一值
* @return base64字符串图片
*/
public static String getImageBase64Str(Producer captchaProducerMath, AdminRedisTemplate adminRedisTemplate,
CaptchaProperties captchaProperties,String uuid){
BufferedImage imageStream = getImageStream(captchaProducerMath, adminRedisTemplate, captchaProperties, uuid);
try (
FastByteArrayOutputStream outputStream = new FastByteArrayOutputStream();
){
ImageIO.write(imageStream, "jpg", outputStream);
return Base64.getEncoder().encodeToString(outputStream.toByteArray());
}catch (Exception e) {
throw new ServiceException("生成验证码异常", e);
}
}
public static BufferedImage getImageStream(Producer captchaProducerMath, AdminRedisTemplate adminRedisTemplate,
CaptchaProperties captchaProperties,String uuid){
String verifyKey = AdminConstant.CAPTCHA_CODE_KEY + uuid;
// 创造图形
String capText = captchaProducerMath.createText();
String capStr = null;
String answer = null;
if (captchaProperties.getVerifyType().equals(VerifyTypeEnum.CALCULATE)){
capStr = capText.substring(0, capText.lastIndexOf(StringPool.AT));
answer = capText.substring(capText.lastIndexOf(StringPool.AT) + 1);
}else if (captchaProperties.getVerifyType().equals(VerifyTypeEnum.RANDOM_LETTER_NUMBER)){
capStr = capText;
answer = capText;
}
BufferedImage image = captchaProducerMath.createImage(capStr);
// 验证码默认有效期为两分钟
adminRedisTemplate.setEx(verifyKey, answer, Duration.ofSeconds(captchaProperties.getExpire()));
return image;
}
}

View File

@ -0,0 +1,51 @@
package com.das.common.captcha;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.core.util.StrUtil;
import com.das.common.constant.AdminConstant;
import com.das.common.utils.AdminRedisTemplate;
import java.time.Duration;
/**
* @author chenhaojie
* @Description
*/
public class CaptchaUtils {
private CaptchaUtils(){}
/**
* 检查验证码是否有效
* @param uuid 唯一键值
* @param codeAnswer 验证码答案
* @param adminRedisTemplate redis工具类
* @return 验证成功为 TRUE 验证失败为 FALSE
*/
public static boolean checkVerificationCode(String uuid, String codeAnswer, AdminRedisTemplate adminRedisTemplate){
String verifyKey = AdminConstant.CAPTCHA_CODE_KEY + uuid;
String answer = adminRedisTemplate.get(verifyKey);
return StrUtil.isNotEmpty(codeAnswer) && answer != null && answer.equals(codeAnswer);
}
/**
* 获取Base64图片
* @param captchaProperties 配置
* @param uuid 唯一值
* @return base64字符串图片
*/
public static String getImageBase64Str(AdminRedisTemplate adminRedisTemplate,
CaptchaProperties captchaProperties,String uuid){
// 使用hutool工具包中的工具类生成图片验证码
//参数 验证码位数 干扰线数量
CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 20);
String codeValue = circleCaptcha.getCode();
String imageBase64 = circleCaptcha.getImageBase64();
String verifyKey = AdminConstant.CAPTCHA_CODE_KEY + uuid;
adminRedisTemplate.setEx(verifyKey, codeValue, Duration.ofSeconds(captchaProperties.getExpire()));
return imageBase64;
}
}

View File

@ -11,26 +11,6 @@ public interface AdminConstant {
*/
String BASE_PACKAGE = "com.das";
/**
* redis分布式所的默认前缀
*/
String REDIS_LOCK_PREFIX = "redis_lock";
/**
* 限流key的默认前缀
*/
String RATE_LIMITER_PREFIX = "rate_limiter";
/**
* 重复提交key的默认前缀
*/
String REPEAT_SUBMIT_PREFIX = "repeat_submit";
/**
* 国际化变量参数名
*/
String ADMIN_LANGUAGE = "admin_language";
/**
* 图形验证码唯一key
*/

View File

@ -2,7 +2,7 @@ package com.das.modules.auth.controller;
import cn.hutool.core.util.IdUtil;
import com.das.common.captcha.CaptchaProperties;
import com.das.common.captcha.CaptchaUtil;
import com.das.common.captcha.CaptchaUtils;
import com.das.common.captcha.CaptchaVO;
import com.das.common.result.R;
import com.das.common.utils.AdminRedisTemplate;
@ -12,14 +12,11 @@ import com.das.modules.auth.domain.request.RefreshTokenRequest;
import com.das.modules.auth.domain.vo.LoginVO;
import com.das.modules.auth.service.ILoginService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.code.kaptcha.Producer;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
@ -33,9 +30,6 @@ import org.springframework.web.bind.annotation.*;
public class LoginController {
@Resource
private ILoginService loginService;
@Resource
private Producer producer;
@Resource
private CaptchaProperties captchaProperties;
@ -73,7 +67,7 @@ public class LoginController {
@PostMapping("/captchaImage")
public R<CaptchaVO> getCaptcha() {
String uuid = IdUtil.fastSimpleUUID();
String imageBase64Str = CaptchaUtil.getImageBase64Str(producer, adminRedisTemplate, captchaProperties, uuid);
String imageBase64Str = CaptchaUtils.getImageBase64Str(adminRedisTemplate, captchaProperties, uuid);
CaptchaVO captchaVO = new CaptchaVO(uuid, imageBase64Str);
return R.success(captchaVO);
}

View File

@ -5,9 +5,8 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.das.common.captcha.CaptchaUtil;
import com.das.common.captcha.CaptchaUtils;
import com.das.common.config.SaTokenProperties;
import com.das.common.utils.AESUtil;
import com.das.common.utils.AdminRedisTemplate;
import com.das.modules.auth.domain.LoginUserDetails;
import com.das.modules.auth.domain.request.LoginRequest;
@ -22,7 +21,6 @@ import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.time.Duration;
@ -57,7 +55,7 @@ public class LoginServiceImpl implements ILoginService {
loginInfo.setMsg("无账号信息");
return loginInfo;
}
if (!CaptchaUtil.checkVerificationCode(key, code, adminRedisTemplate)) {
if (!CaptchaUtils.checkVerificationCode(key, code, adminRedisTemplate)) {
loginInfo.setMsg("验证码不正确");
return loginInfo;
}