mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-01 02:38:43 +08:00 
			
		
		
		
	增加图片验证码接口
This commit is contained in:
		| @@ -0,0 +1,9 @@ | ||||
| package cn.iocoder.dashboard.framework.captcha.config; | ||||
|  | ||||
| import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
|  | ||||
| @Configuration | ||||
| @EnableConfigurationProperties(CaptchaProperties.class) | ||||
| public class CaptchaConfig { | ||||
| } | ||||
| @@ -0,0 +1,31 @@ | ||||
| package cn.iocoder.dashboard.framework.captcha.config; | ||||
|  | ||||
| import lombok.Data; | ||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
|  | ||||
| import javax.validation.constraints.NotNull; | ||||
| import java.time.Duration; | ||||
|  | ||||
| @ConfigurationProperties(prefix = "yudao.captcha") | ||||
| @Validated | ||||
| @Data | ||||
| public class CaptchaProperties { | ||||
|  | ||||
|     /** | ||||
|      * 验证码的过期时间 | ||||
|      */ | ||||
|     @NotNull(message = "验证码的过期时间不为空") | ||||
|     private Duration timeout; | ||||
|     /** | ||||
|      * 验证码的高度 | ||||
|      */ | ||||
|     @NotNull(message = "验证码的高度不能为空") | ||||
|     private Integer height; | ||||
|     /** | ||||
|      * 验证码的宽度 | ||||
|      */ | ||||
|     @NotNull(message = "验证码的宽度不能为空") | ||||
|     private Integer width; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,4 @@ | ||||
| /** | ||||
|  * 基于 Hutool captcha 库,实现验证码功能 | ||||
|  */ | ||||
| package cn.iocoder.dashboard.framework.captcha; | ||||
| @@ -0,0 +1,2 @@ | ||||
| ### 请求 /captcha/get-image 接口 => 成功 | ||||
| GET {{baseUrl}}/captcha/get-image | ||||
| @@ -0,0 +1,30 @@ | ||||
| package cn.iocoder.dashboard.modules.system.controller.common; | ||||
|  | ||||
| import cn.iocoder.dashboard.common.pojo.CommonResult; | ||||
| import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageRespVO; | ||||
| import cn.iocoder.dashboard.modules.system.service.common.SysCaptchaService; | ||||
| import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiOperation; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
|  | ||||
| import static cn.iocoder.dashboard.common.pojo.CommonResult.success; | ||||
|  | ||||
| @Api(tags = "验证码 API") | ||||
| @RestController | ||||
| @RequestMapping("/captcha") | ||||
| public class SysCaptchaController { | ||||
|  | ||||
|     @Resource | ||||
|     private SysCaptchaService captchaService; | ||||
|  | ||||
|     @ApiOperation("生成图片验证码") | ||||
|     @GetMapping("/get-image") | ||||
|     private CommonResult<SysCaptchaImageRespVO> getCaptchaImage() { | ||||
|         return success(captchaService.getCaptchaImage()); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,23 @@ | ||||
| package cn.iocoder.dashboard.modules.system.controller.common.vo; | ||||
|  | ||||
| import io.swagger.annotations.ApiModel; | ||||
| import io.swagger.annotations.ApiModelProperty; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Builder; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
|  | ||||
| @ApiModel("验证码图片 Response VO") | ||||
| @Data | ||||
| @Builder | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
| public class SysCaptchaImageRespVO { | ||||
|  | ||||
|     @ApiModelProperty(value = "uuid", required = true, example = "1b3b7d00-83a8-4638-9e37-d67011855968", notes = "通过该 uuid 作为该验证码的标识") | ||||
|     private String uuid; | ||||
|  | ||||
|     @ApiModelProperty(value = "图片", required = true, notes = "验证码的图片内容,使用 Base64 编码") | ||||
|     private String img; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,18 @@ | ||||
| package cn.iocoder.dashboard.modules.system.convert.common; | ||||
|  | ||||
| import cn.hutool.captcha.AbstractCaptcha; | ||||
| import cn.hutool.captcha.ICaptcha; | ||||
| import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageRespVO; | ||||
| import org.mapstruct.Mapper; | ||||
| import org.mapstruct.factory.Mappers; | ||||
|  | ||||
| @Mapper | ||||
| public interface SysCaptchaConvert { | ||||
|  | ||||
|     SysCaptchaConvert INSTANCE = Mappers.getMapper(SysCaptchaConvert.class); | ||||
|  | ||||
|     default SysCaptchaImageRespVO convert(String uuid, AbstractCaptcha captcha) { | ||||
|         return SysCaptchaImageRespVO.builder().uuid(uuid).img(captcha.getImageBase64()).build(); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,6 @@ | ||||
| /** | ||||
|  * 提供 POJO 类的实体转换 | ||||
|  * | ||||
|  * 目前使用 MapStruct 框架 | ||||
|  */ | ||||
| package cn.iocoder.dashboard.modules.system.convert; | ||||
| @@ -0,0 +1 @@ | ||||
| <http://www.iocoder.cn/Spring-Boot/MapStruct/?dashboard> | ||||
| @@ -0,0 +1,32 @@ | ||||
| package cn.iocoder.dashboard.modules.system.dal.redis; | ||||
|  | ||||
| import cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine; | ||||
| import cn.iocoder.dashboard.framework.security.core.LoginUser; | ||||
|  | ||||
| import java.time.Duration; | ||||
|  | ||||
| import static cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING; | ||||
| import static cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine.TIMEOUT_DYNAMIC; | ||||
|  | ||||
| /** | ||||
|  * Redis Key 枚举类 | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| public interface RedisKeyConstants { | ||||
|  | ||||
|     /** | ||||
|      * {@link LoginUser} 的缓存 | ||||
|      * | ||||
|      * key 的 format 的参数是 sessionId | ||||
|      */ | ||||
|     RedisKeyDefine LOGIN_USER = new RedisKeyDefine("login_user:%s", STRING, LoginUser.class, Duration.ofMinutes(30)); | ||||
|  | ||||
|     /** | ||||
|      * 验证码的缓存 | ||||
|      * | ||||
|      * key 的 format 的参数是 uuid | ||||
|      */ | ||||
|     RedisKeyDefine CAPTCHA_CODE = new RedisKeyDefine("captcha_code:%s", STRING, String.class, TIMEOUT_DYNAMIC); | ||||
|  | ||||
| } | ||||
| @@ -1,4 +0,0 @@ | ||||
| package cn.iocoder.dashboard.modules.system.dal.redis; | ||||
|  | ||||
| public class RedisKeyContants { | ||||
| } | ||||
| @@ -0,0 +1,42 @@ | ||||
| package cn.iocoder.dashboard.modules.system.dal.redis.dao.auth; | ||||
|  | ||||
| import cn.iocoder.dashboard.framework.security.core.LoginUser; | ||||
| import com.alibaba.fastjson.JSON; | ||||
| import org.springframework.data.redis.core.StringRedisTemplate; | ||||
| import org.springframework.stereotype.Repository; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
|  | ||||
| import static cn.iocoder.dashboard.modules.system.dal.redis.RedisKeyConstants.LOGIN_USER; | ||||
|  | ||||
| /** | ||||
|  * {@link LoginUser} 的 RedisDAO | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| @Repository | ||||
| public class SysLoginUserRedisDAO { | ||||
|  | ||||
|     @Resource | ||||
|     private StringRedisTemplate stringRedisTemplate; | ||||
|  | ||||
|     public LoginUser get(String sessionId) { | ||||
|         String redisKey = formatKey(sessionId); | ||||
|         return JSON.parseObject(stringRedisTemplate.opsForValue().get(redisKey), LoginUser.class); | ||||
|     } | ||||
|  | ||||
|     public void set(String sessionId, LoginUser loginUser) { | ||||
|         String redisKey = formatKey(sessionId); | ||||
|         stringRedisTemplate.opsForValue().set(redisKey, JSON.toJSONString(loginUser), LOGIN_USER.getTimeout()); | ||||
|     } | ||||
|  | ||||
|     public void delete(String accessToken) { | ||||
|         String redisKey = formatKey(accessToken); | ||||
|         stringRedisTemplate.delete(redisKey); | ||||
|     } | ||||
|  | ||||
|     private static String formatKey(String sessionId) { | ||||
|         return String.format(LOGIN_USER.getKeyTemplate(), sessionId); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,44 @@ | ||||
| package cn.iocoder.dashboard.modules.system.dal.redis.dao.common; | ||||
|  | ||||
| import cn.iocoder.dashboard.framework.security.core.LoginUser; | ||||
| import com.alibaba.fastjson.JSON; | ||||
| import org.springframework.data.redis.core.StringRedisTemplate; | ||||
| import org.springframework.stereotype.Repository; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
|  | ||||
| import java.time.Duration; | ||||
|  | ||||
| import static cn.iocoder.dashboard.modules.system.dal.redis.RedisKeyConstants.CAPTCHA_CODE; | ||||
|  | ||||
| /** | ||||
|  * 验证码的 Redis DAO | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| @Repository | ||||
| public class SysCaptchaRedisDAO { | ||||
|  | ||||
|     @Resource | ||||
|     private StringRedisTemplate stringRedisTemplate; | ||||
|  | ||||
|     public String get(String uuid) { | ||||
|         String redisKey = formatKey(uuid); | ||||
|         return stringRedisTemplate.opsForValue().get(redisKey); | ||||
|     } | ||||
|  | ||||
|     public void set(String uuid, String code, Duration timeout) { | ||||
|         String redisKey = formatKey(uuid); | ||||
|         stringRedisTemplate.opsForValue().set(redisKey, code, timeout); | ||||
|     } | ||||
|  | ||||
|     public void delete(String uuid) { | ||||
|         String redisKey = formatKey(uuid); | ||||
|         stringRedisTemplate.delete(redisKey); | ||||
|     } | ||||
|  | ||||
|     private static String formatKey(String uuid) { | ||||
|         return String.format(CAPTCHA_CODE.getKeyTemplate(), uuid); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,4 @@ | ||||
| /** | ||||
|  * 提供 Redis 访问的 DAO | ||||
|  */ | ||||
| package cn.iocoder.dashboard.modules.system.dal.redis.dao; | ||||
| @@ -0,0 +1,12 @@ | ||||
| package cn.iocoder.dashboard.modules.system.service.common; | ||||
|  | ||||
| import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageRespVO; | ||||
|  | ||||
| /** | ||||
|  * 验证码 Service 接口 | ||||
|  */ | ||||
| public interface SysCaptchaService { | ||||
|  | ||||
|     SysCaptchaImageRespVO getCaptchaImage(); | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,38 @@ | ||||
| package cn.iocoder.dashboard.modules.system.service.common.impl; | ||||
|  | ||||
| import cn.hutool.captcha.CaptchaUtil; | ||||
| import cn.hutool.captcha.CircleCaptcha; | ||||
| import cn.hutool.core.util.IdUtil; | ||||
| import cn.iocoder.dashboard.framework.captcha.config.CaptchaProperties; | ||||
| import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageRespVO; | ||||
| import cn.iocoder.dashboard.modules.system.convert.common.SysCaptchaConvert; | ||||
| import cn.iocoder.dashboard.modules.system.dal.redis.dao.common.SysCaptchaRedisDAO; | ||||
| import cn.iocoder.dashboard.modules.system.service.common.SysCaptchaService; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
|  | ||||
| /** | ||||
|  * 验证码 Service 实现类 | ||||
|  */ | ||||
| @Service | ||||
| public class SysCaptchaServiceImpl implements SysCaptchaService { | ||||
|  | ||||
|     @Resource | ||||
|     private CaptchaProperties captchaProperties; | ||||
|  | ||||
|     @Resource | ||||
|     private SysCaptchaRedisDAO captchaRedisDAO; | ||||
|  | ||||
|     @Override | ||||
|     public SysCaptchaImageRespVO getCaptchaImage() { | ||||
|         // 生成验证码 | ||||
|         CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(captchaProperties.getWidth(), captchaProperties.getHeight()); | ||||
|         // 缓存到 Redis 中 | ||||
|         String uuid = IdUtil.fastSimpleUUID(); | ||||
|         captchaRedisDAO.set(uuid, captcha.getCode(), captchaProperties.getTimeout()); | ||||
|         // 返回 | ||||
|         return SysCaptchaConvert.INSTANCE.convert(uuid, captcha); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,4 +1,6 @@ | ||||
| spring: | ||||
|   application: | ||||
|     name: dashboard | ||||
|   # 数据源配置项 TODO 多数据源;TODO 监控配置 | ||||
|   datasource: | ||||
|     url: jdbc:mysql://127.0.1:3306/ruoyi-vue-pro?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||||
| @@ -21,9 +23,14 @@ yudao: | ||||
|   security: | ||||
|     token-header: Authorization | ||||
|     token-secret: abcdefghijklmnopqrstuvwxyz | ||||
|     token-expires: 30m | ||||
|     token-timeout: 1d | ||||
|     session-timeout: 30m | ||||
|   swagger: | ||||
|     title: 管理后台 | ||||
|     description: 提供管理员管理的所有功能 | ||||
|     version: 1.0.0 | ||||
|     base-package: cn.iocoder.dashboard.modules | ||||
|   captcha: | ||||
|     timeout: 5m | ||||
|     width: 160 | ||||
|     height: 60 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV