Commit e85c342696821195f369a8fdcbfa49a029327361

Authored by YunaiV
1 parent ca90fcb8

增加图片验证码接口

Showing 18 changed files with 331 additions and 11 deletions
@@ -49,8 +49,8 @@ @@ -49,8 +49,8 @@
49 <mybatis-plus.version>3.4.1</mybatis-plus.version> 49 <mybatis-plus.version>3.4.1</mybatis-plus.version>
50 <redisson.version>3.13.6</redisson.version> 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 <jjwt.version>0.9.1</jjwt.version> 54 <jjwt.version>0.9.1</jjwt.version>
55 <fastjson.version>1.2.75</fastjson.version> 55 <fastjson.version>1.2.75</fastjson.version>
56 <hutool.version>5.5.6</hutool.version> 56 <hutool.version>5.5.6</hutool.version>
@@ -252,7 +252,7 @@ @@ -252,7 +252,7 @@
252 <dependency> 252 <dependency>
253 <groupId>org.projectlombok</groupId> 253 <groupId>org.projectlombok</groupId>
254 <artifactId>lombok</artifactId> 254 <artifactId>lombok</artifactId>
255 - <version>${org.projectlombok.version}</version> 255 + <version>${lombok.version}</version>
256 </dependency> 256 </dependency>
257 257
258 <dependency> 258 <dependency>
@@ -270,7 +270,7 @@ @@ -270,7 +270,7 @@
270 <dependency> 270 <dependency>
271 <groupId>org.projectlombok</groupId> 271 <groupId>org.projectlombok</groupId>
272 <artifactId>lombok</artifactId> 272 <artifactId>lombok</artifactId>
273 - <version>${org.projectlombok.version}</version> 273 + <version>${lombok.version}</version>
274 </dependency> 274 </dependency>
275 275
276 <dependency> 276 <dependency>
@@ -281,10 +281,31 @@ @@ -281,10 +281,31 @@
281 </dependency> 281 </dependency>
282 282
283 <dependency> 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 <groupId>cn.hutool</groupId> 295 <groupId>cn.hutool</groupId>
285 <artifactId>hutool-core</artifactId> 296 <artifactId>hutool-core</artifactId>
286 <version>${hutool.version}</version> 297 <version>${hutool.version}</version>
287 </dependency> 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 </dependencies> 309 </dependencies>
289 310
290 311
@@ -303,12 +324,12 @@ @@ -303,12 +324,12 @@
303 <path> 324 <path>
304 <groupId>org.mapstruct</groupId> 325 <groupId>org.mapstruct</groupId>
305 <artifactId>mapstruct-processor</artifactId> 326 <artifactId>mapstruct-processor</artifactId>
306 - <version>${org.mapstruct.version}</version> 327 + <version>${mapstruct.version}</version>
307 </path> 328 </path>
308 <path> 329 <path>
309 <groupId>org.projectlombok</groupId> 330 <groupId>org.projectlombok</groupId>
310 <artifactId>lombok</artifactId> 331 <artifactId>lombok</artifactId>
311 - <version>${org.projectlombok.version}</version> 332 + <version>${lombok.version}</version>
312 </path> 333 </path>
313 </annotationProcessorPaths> 334 </annotationProcessorPaths>
314 </configuration> 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
  1 +/**
  2 + * 基于 Hutool captcha 库,实现验证码功能
  3 + */
  4 +package cn.iocoder.dashboard.framework.captcha;
src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.http 0 → 100644
  1 +### 请求 /captcha/get-image 接口 => 成功
  2 +GET {{baseUrl}}/captcha/get-image
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
  1 +/**
  2 + * 提供 POJO 类的实体转换
  3 + *
  4 + * 目前使用 MapStruct 框架
  5 + */
  6 +package cn.iocoder.dashboard.modules.system.convert;
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
1 -package cn.iocoder.dashboard.modules.system.dal.redis;  
2 -  
3 -public class RedisKeyContants {  
4 -}  
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
  1 +/**
  2 + * 提供 Redis 访问的 DAO
  3 + */
  4 +package cn.iocoder.dashboard.modules.system.dal.redis.dao;
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 spring: 1 spring:
  2 + application:
  3 + name: dashboard
2 # 数据源配置项 TODO 多数据源;TODO 监控配置 4 # 数据源配置项 TODO 多数据源;TODO 监控配置
3 datasource: 5 datasource:
4 url: jdbc:mysql://127.0.1:3306/ruoyi-vue-pro?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT 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,9 +23,14 @@ yudao:
21 security: 23 security:
22 token-header: Authorization 24 token-header: Authorization
23 token-secret: abcdefghijklmnopqrstuvwxyz 25 token-secret: abcdefghijklmnopqrstuvwxyz
24 - token-expires: 30m 26 + token-timeout: 1d
  27 + session-timeout: 30m
25 swagger: 28 swagger:
26 title: 管理后台 29 title: 管理后台
27 description: 提供管理员管理的所有功能 30 description: 提供管理员管理的所有功能
28 version: 1.0.0 31 version: 1.0.0
29 base-package: cn.iocoder.dashboard.modules 32 base-package: cn.iocoder.dashboard.modules
  33 + captcha:
  34 + timeout: 5m
  35 + width: 160
  36 + height: 60