das项目结构修改
This commit is contained in:
parent
c0f137bb4a
commit
2e0c3a1032
@ -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>
|
||||
|
@ -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 我们可以自己设置yes,no
|
||||
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 我们可以自己设置yes,no
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
51
das/src/main/java/com/das/common/captcha/CaptchaUtils.java
Normal file
51
das/src/main/java/com/das/common/captcha/CaptchaUtils.java
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user