Commit e85c342696821195f369a8fdcbfa49a029327361
1 parent
ca90fcb8
增加图片验证码接口
Showing
18 changed files
with
331 additions
and
11 deletions
pom.xml
| ... | ... | @@ -49,8 +49,8 @@ |
| 49 | 49 | <mybatis-plus.version>3.4.1</mybatis-plus.version> |
| 50 | 50 | <redisson.version>3.13.6</redisson.version> |
| 51 | 51 | <!-- 工具类相关 --> |
| 52 | - <org.projectlombok.version>1.16.14</org.projectlombok.version> | |
| 53 | - <org.mapstruct.version>1.3.0.Final</org.mapstruct.version> | |
| 52 | + <lombok.version>1.16.14</lombok.version> | |
| 53 | + <mapstruct.version>1.4.1.Final</mapstruct.version> | |
| 54 | 54 | <jjwt.version>0.9.1</jjwt.version> |
| 55 | 55 | <fastjson.version>1.2.75</fastjson.version> |
| 56 | 56 | <hutool.version>5.5.6</hutool.version> |
| ... | ... | @@ -252,7 +252,7 @@ |
| 252 | 252 | <dependency> |
| 253 | 253 | <groupId>org.projectlombok</groupId> |
| 254 | 254 | <artifactId>lombok</artifactId> |
| 255 | - <version>${org.projectlombok.version}</version> | |
| 255 | + <version>${lombok.version}</version> | |
| 256 | 256 | </dependency> |
| 257 | 257 | |
| 258 | 258 | <dependency> |
| ... | ... | @@ -270,7 +270,7 @@ |
| 270 | 270 | <dependency> |
| 271 | 271 | <groupId>org.projectlombok</groupId> |
| 272 | 272 | <artifactId>lombok</artifactId> |
| 273 | - <version>${org.projectlombok.version}</version> | |
| 273 | + <version>${lombok.version}</version> | |
| 274 | 274 | </dependency> |
| 275 | 275 | |
| 276 | 276 | <dependency> |
| ... | ... | @@ -281,10 +281,31 @@ |
| 281 | 281 | </dependency> |
| 282 | 282 | |
| 283 | 283 | <dependency> |
| 284 | + <groupId>org.mapstruct</groupId> | |
| 285 | + <artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher --> | |
| 286 | + <version>${mapstruct.version}</version> | |
| 287 | + </dependency> | |
| 288 | + <dependency> | |
| 289 | + <groupId>org.mapstruct</groupId> | |
| 290 | + <artifactId>mapstruct-jdk8</artifactId> | |
| 291 | + <version>${mapstruct.version}</version> | |
| 292 | + </dependency> | |
| 293 | + | |
| 294 | + <dependency> | |
| 284 | 295 | <groupId>cn.hutool</groupId> |
| 285 | 296 | <artifactId>hutool-core</artifactId> |
| 286 | 297 | <version>${hutool.version}</version> |
| 287 | 298 | </dependency> |
| 299 | + <dependency> | |
| 300 | + <groupId>cn.hutool</groupId> | |
| 301 | + <artifactId>hutool-extra</artifactId> | |
| 302 | + <version>${hutool.version}</version> | |
| 303 | + </dependency> | |
| 304 | + <dependency> | |
| 305 | + <groupId>cn.hutool</groupId> | |
| 306 | + <artifactId>hutool-captcha</artifactId> | |
| 307 | + <version>${hutool.version}</version> | |
| 308 | + </dependency> | |
| 288 | 309 | </dependencies> |
| 289 | 310 | |
| 290 | 311 | |
| ... | ... | @@ -303,12 +324,12 @@ |
| 303 | 324 | <path> |
| 304 | 325 | <groupId>org.mapstruct</groupId> |
| 305 | 326 | <artifactId>mapstruct-processor</artifactId> |
| 306 | - <version>${org.mapstruct.version}</version> | |
| 327 | + <version>${mapstruct.version}</version> | |
| 307 | 328 | </path> |
| 308 | 329 | <path> |
| 309 | 330 | <groupId>org.projectlombok</groupId> |
| 310 | 331 | <artifactId>lombok</artifactId> |
| 311 | - <version>${org.projectlombok.version}</version> | |
| 332 | + <version>${lombok.version}</version> | |
| 312 | 333 | </path> |
| 313 | 334 | </annotationProcessorPaths> |
| 314 | 335 | </configuration> | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaConfig.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.captcha.config; | |
| 2 | + | |
| 3 | +import org.springframework.boot.context.properties.EnableConfigurationProperties; | |
| 4 | +import org.springframework.context.annotation.Configuration; | |
| 5 | + | |
| 6 | +@Configuration | |
| 7 | +@EnableConfigurationProperties(CaptchaProperties.class) | |
| 8 | +public class CaptchaConfig { | |
| 9 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaProperties.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.captcha.config; | |
| 2 | + | |
| 3 | +import lombok.Data; | |
| 4 | +import org.springframework.boot.context.properties.ConfigurationProperties; | |
| 5 | +import org.springframework.validation.annotation.Validated; | |
| 6 | + | |
| 7 | +import javax.validation.constraints.NotNull; | |
| 8 | +import java.time.Duration; | |
| 9 | + | |
| 10 | +@ConfigurationProperties(prefix = "yudao.captcha") | |
| 11 | +@Validated | |
| 12 | +@Data | |
| 13 | +public class CaptchaProperties { | |
| 14 | + | |
| 15 | + /** | |
| 16 | + * 验证码的过期时间 | |
| 17 | + */ | |
| 18 | + @NotNull(message = "验证码的过期时间不为空") | |
| 19 | + private Duration timeout; | |
| 20 | + /** | |
| 21 | + * 验证码的高度 | |
| 22 | + */ | |
| 23 | + @NotNull(message = "验证码的高度不能为空") | |
| 24 | + private Integer height; | |
| 25 | + /** | |
| 26 | + * 验证码的宽度 | |
| 27 | + */ | |
| 28 | + @NotNull(message = "验证码的宽度不能为空") | |
| 29 | + private Integer width; | |
| 30 | + | |
| 31 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/captcha/package-info.java
0 → 100644
src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.http
0 → 100644
src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.controller.common; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.common.pojo.CommonResult; | |
| 4 | +import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageRespVO; | |
| 5 | +import cn.iocoder.dashboard.modules.system.service.common.SysCaptchaService; | |
| 6 | +import io.swagger.annotations.Api; | |
| 7 | +import io.swagger.annotations.ApiOperation; | |
| 8 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 9 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 10 | +import org.springframework.web.bind.annotation.RestController; | |
| 11 | + | |
| 12 | +import javax.annotation.Resource; | |
| 13 | + | |
| 14 | +import static cn.iocoder.dashboard.common.pojo.CommonResult.success; | |
| 15 | + | |
| 16 | +@Api(tags = "验证码 API") | |
| 17 | +@RestController | |
| 18 | +@RequestMapping("/captcha") | |
| 19 | +public class SysCaptchaController { | |
| 20 | + | |
| 21 | + @Resource | |
| 22 | + private SysCaptchaService captchaService; | |
| 23 | + | |
| 24 | + @ApiOperation("生成图片验证码") | |
| 25 | + @GetMapping("/get-image") | |
| 26 | + private CommonResult<SysCaptchaImageRespVO> getCaptchaImage() { | |
| 27 | + return success(captchaService.getCaptchaImage()); | |
| 28 | + } | |
| 29 | + | |
| 30 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/controller/common/vo/SysCaptchaImageRespVO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.controller.common.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.AllArgsConstructor; | |
| 6 | +import lombok.Builder; | |
| 7 | +import lombok.Data; | |
| 8 | +import lombok.NoArgsConstructor; | |
| 9 | + | |
| 10 | +@ApiModel("验证码图片 Response VO") | |
| 11 | +@Data | |
| 12 | +@Builder | |
| 13 | +@NoArgsConstructor | |
| 14 | +@AllArgsConstructor | |
| 15 | +public class SysCaptchaImageRespVO { | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "uuid", required = true, example = "1b3b7d00-83a8-4638-9e37-d67011855968", notes = "通过该 uuid 作为该验证码的标识") | |
| 18 | + private String uuid; | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "图片", required = true, notes = "验证码的图片内容,使用 Base64 编码") | |
| 21 | + private String img; | |
| 22 | + | |
| 23 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/convert/common/SysCaptchaConvert.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.convert.common; | |
| 2 | + | |
| 3 | +import cn.hutool.captcha.AbstractCaptcha; | |
| 4 | +import cn.hutool.captcha.ICaptcha; | |
| 5 | +import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageRespVO; | |
| 6 | +import org.mapstruct.Mapper; | |
| 7 | +import org.mapstruct.factory.Mappers; | |
| 8 | + | |
| 9 | +@Mapper | |
| 10 | +public interface SysCaptchaConvert { | |
| 11 | + | |
| 12 | + SysCaptchaConvert INSTANCE = Mappers.getMapper(SysCaptchaConvert.class); | |
| 13 | + | |
| 14 | + default SysCaptchaImageRespVO convert(String uuid, AbstractCaptcha captcha) { | |
| 15 | + return SysCaptchaImageRespVO.builder().uuid(uuid).img(captcha.getImageBase64()).build(); | |
| 16 | + } | |
| 17 | + | |
| 18 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/convert/package-info.java
0 → 100644
src/main/java/cn/iocoder/dashboard/modules/system/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md
0 → 100644
| 1 | +<http://www.iocoder.cn/Spring-Boot/MapStruct/?dashboard> | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/RedisKeyConstants.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.dal.redis; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine; | |
| 4 | +import cn.iocoder.dashboard.framework.security.core.LoginUser; | |
| 5 | + | |
| 6 | +import java.time.Duration; | |
| 7 | + | |
| 8 | +import static cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING; | |
| 9 | +import static cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine.TIMEOUT_DYNAMIC; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * Redis Key 枚举类 | |
| 13 | + * | |
| 14 | + * @author 芋道源码 | |
| 15 | + */ | |
| 16 | +public interface RedisKeyConstants { | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * {@link LoginUser} 的缓存 | |
| 20 | + * | |
| 21 | + * key 的 format 的参数是 sessionId | |
| 22 | + */ | |
| 23 | + RedisKeyDefine LOGIN_USER = new RedisKeyDefine("login_user:%s", STRING, LoginUser.class, Duration.ofMinutes(30)); | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 验证码的缓存 | |
| 27 | + * | |
| 28 | + * key 的 format 的参数是 uuid | |
| 29 | + */ | |
| 30 | + RedisKeyDefine CAPTCHA_CODE = new RedisKeyDefine("captcha_code:%s", STRING, String.class, TIMEOUT_DYNAMIC); | |
| 31 | + | |
| 32 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/RedisKeyContants.java deleted
src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/dao/auth/SysLoginUserRedisDAO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.dal.redis.dao.auth; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.framework.security.core.LoginUser; | |
| 4 | +import com.alibaba.fastjson.JSON; | |
| 5 | +import org.springframework.data.redis.core.StringRedisTemplate; | |
| 6 | +import org.springframework.stereotype.Repository; | |
| 7 | + | |
| 8 | +import javax.annotation.Resource; | |
| 9 | + | |
| 10 | +import static cn.iocoder.dashboard.modules.system.dal.redis.RedisKeyConstants.LOGIN_USER; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * {@link LoginUser} 的 RedisDAO | |
| 14 | + * | |
| 15 | + * @author 芋道源码 | |
| 16 | + */ | |
| 17 | +@Repository | |
| 18 | +public class SysLoginUserRedisDAO { | |
| 19 | + | |
| 20 | + @Resource | |
| 21 | + private StringRedisTemplate stringRedisTemplate; | |
| 22 | + | |
| 23 | + public LoginUser get(String sessionId) { | |
| 24 | + String redisKey = formatKey(sessionId); | |
| 25 | + return JSON.parseObject(stringRedisTemplate.opsForValue().get(redisKey), LoginUser.class); | |
| 26 | + } | |
| 27 | + | |
| 28 | + public void set(String sessionId, LoginUser loginUser) { | |
| 29 | + String redisKey = formatKey(sessionId); | |
| 30 | + stringRedisTemplate.opsForValue().set(redisKey, JSON.toJSONString(loginUser), LOGIN_USER.getTimeout()); | |
| 31 | + } | |
| 32 | + | |
| 33 | + public void delete(String accessToken) { | |
| 34 | + String redisKey = formatKey(accessToken); | |
| 35 | + stringRedisTemplate.delete(redisKey); | |
| 36 | + } | |
| 37 | + | |
| 38 | + private static String formatKey(String sessionId) { | |
| 39 | + return String.format(LOGIN_USER.getKeyTemplate(), sessionId); | |
| 40 | + } | |
| 41 | + | |
| 42 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/dao/common/SysCaptchaRedisDAO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.dal.redis.dao.common; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.framework.security.core.LoginUser; | |
| 4 | +import com.alibaba.fastjson.JSON; | |
| 5 | +import org.springframework.data.redis.core.StringRedisTemplate; | |
| 6 | +import org.springframework.stereotype.Repository; | |
| 7 | + | |
| 8 | +import javax.annotation.Resource; | |
| 9 | + | |
| 10 | +import java.time.Duration; | |
| 11 | + | |
| 12 | +import static cn.iocoder.dashboard.modules.system.dal.redis.RedisKeyConstants.CAPTCHA_CODE; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * 验证码的 Redis DAO | |
| 16 | + * | |
| 17 | + * @author 芋道源码 | |
| 18 | + */ | |
| 19 | +@Repository | |
| 20 | +public class SysCaptchaRedisDAO { | |
| 21 | + | |
| 22 | + @Resource | |
| 23 | + private StringRedisTemplate stringRedisTemplate; | |
| 24 | + | |
| 25 | + public String get(String uuid) { | |
| 26 | + String redisKey = formatKey(uuid); | |
| 27 | + return stringRedisTemplate.opsForValue().get(redisKey); | |
| 28 | + } | |
| 29 | + | |
| 30 | + public void set(String uuid, String code, Duration timeout) { | |
| 31 | + String redisKey = formatKey(uuid); | |
| 32 | + stringRedisTemplate.opsForValue().set(redisKey, code, timeout); | |
| 33 | + } | |
| 34 | + | |
| 35 | + public void delete(String uuid) { | |
| 36 | + String redisKey = formatKey(uuid); | |
| 37 | + stringRedisTemplate.delete(redisKey); | |
| 38 | + } | |
| 39 | + | |
| 40 | + private static String formatKey(String uuid) { | |
| 41 | + return String.format(CAPTCHA_CODE.getKeyTemplate(), uuid); | |
| 42 | + } | |
| 43 | + | |
| 44 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/dao/package-info.java
0 → 100644
src/main/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaService.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.service.common; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageRespVO; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * 验证码 Service 接口 | |
| 7 | + */ | |
| 8 | +public interface SysCaptchaService { | |
| 9 | + | |
| 10 | + SysCaptchaImageRespVO getCaptchaImage(); | |
| 11 | + | |
| 12 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/common/impl/SysCaptchaServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.service.common.impl; | |
| 2 | + | |
| 3 | +import cn.hutool.captcha.CaptchaUtil; | |
| 4 | +import cn.hutool.captcha.CircleCaptcha; | |
| 5 | +import cn.hutool.core.util.IdUtil; | |
| 6 | +import cn.iocoder.dashboard.framework.captcha.config.CaptchaProperties; | |
| 7 | +import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageRespVO; | |
| 8 | +import cn.iocoder.dashboard.modules.system.convert.common.SysCaptchaConvert; | |
| 9 | +import cn.iocoder.dashboard.modules.system.dal.redis.dao.common.SysCaptchaRedisDAO; | |
| 10 | +import cn.iocoder.dashboard.modules.system.service.common.SysCaptchaService; | |
| 11 | +import org.springframework.stereotype.Service; | |
| 12 | + | |
| 13 | +import javax.annotation.Resource; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * 验证码 Service 实现类 | |
| 17 | + */ | |
| 18 | +@Service | |
| 19 | +public class SysCaptchaServiceImpl implements SysCaptchaService { | |
| 20 | + | |
| 21 | + @Resource | |
| 22 | + private CaptchaProperties captchaProperties; | |
| 23 | + | |
| 24 | + @Resource | |
| 25 | + private SysCaptchaRedisDAO captchaRedisDAO; | |
| 26 | + | |
| 27 | + @Override | |
| 28 | + public SysCaptchaImageRespVO getCaptchaImage() { | |
| 29 | + // 生成验证码 | |
| 30 | + CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(captchaProperties.getWidth(), captchaProperties.getHeight()); | |
| 31 | + // 缓存到 Redis 中 | |
| 32 | + String uuid = IdUtil.fastSimpleUUID(); | |
| 33 | + captchaRedisDAO.set(uuid, captcha.getCode(), captchaProperties.getTimeout()); | |
| 34 | + // 返回 | |
| 35 | + return SysCaptchaConvert.INSTANCE.convert(uuid, captcha); | |
| 36 | + } | |
| 37 | + | |
| 38 | +} | ... | ... |
src/main/resources/application.yaml
| 1 | 1 | spring: |
| 2 | + application: | |
| 3 | + name: dashboard | |
| 2 | 4 | # 数据源配置项 TODO 多数据源;TODO 监控配置 |
| 3 | 5 | datasource: |
| 4 | 6 | url: jdbc:mysql://127.0.1:3306/ruoyi-vue-pro?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT |
| ... | ... | @@ -21,9 +23,14 @@ yudao: |
| 21 | 23 | security: |
| 22 | 24 | token-header: Authorization |
| 23 | 25 | token-secret: abcdefghijklmnopqrstuvwxyz |
| 24 | - token-expires: 30m | |
| 26 | + token-timeout: 1d | |
| 27 | + session-timeout: 30m | |
| 25 | 28 | swagger: |
| 26 | 29 | title: 管理后台 |
| 27 | 30 | description: 提供管理员管理的所有功能 |
| 28 | 31 | version: 1.0.0 |
| 29 | 32 | base-package: cn.iocoder.dashboard.modules |
| 33 | + captcha: | |
| 34 | + timeout: 5m | |
| 35 | + width: 160 | |
| 36 | + height: 60 | ... | ... |