mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 09:11:52 +08:00
增加图片验证码接口
This commit is contained in:
parent
ca90fcb8fa
commit
e85c342696
33
pom.xml
33
pom.xml
@ -49,8 +49,8 @@
|
|||||||
<mybatis-plus.version>3.4.1</mybatis-plus.version>
|
<mybatis-plus.version>3.4.1</mybatis-plus.version>
|
||||||
<redisson.version>3.13.6</redisson.version>
|
<redisson.version>3.13.6</redisson.version>
|
||||||
<!-- 工具类相关 -->
|
<!-- 工具类相关 -->
|
||||||
<org.projectlombok.version>1.16.14</org.projectlombok.version>
|
<lombok.version>1.16.14</lombok.version>
|
||||||
<org.mapstruct.version>1.3.0.Final</org.mapstruct.version>
|
<mapstruct.version>1.4.1.Final</mapstruct.version>
|
||||||
<jjwt.version>0.9.1</jjwt.version>
|
<jjwt.version>0.9.1</jjwt.version>
|
||||||
<fastjson.version>1.2.75</fastjson.version>
|
<fastjson.version>1.2.75</fastjson.version>
|
||||||
<hutool.version>5.5.6</hutool.version>
|
<hutool.version>5.5.6</hutool.version>
|
||||||
@ -252,7 +252,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>${org.projectlombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -270,7 +270,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>${org.projectlombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -280,11 +280,32 @@
|
|||||||
<version>1.21</version>
|
<version>1.21</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-jdk8</artifactId>
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-core</artifactId>
|
<artifactId>hutool-core</artifactId>
|
||||||
<version>${hutool.version}</version>
|
<version>${hutool.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-extra</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-captcha</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
@ -303,12 +324,12 @@
|
|||||||
<path>
|
<path>
|
||||||
<groupId>org.mapstruct</groupId>
|
<groupId>org.mapstruct</groupId>
|
||||||
<artifactId>mapstruct-processor</artifactId>
|
<artifactId>mapstruct-processor</artifactId>
|
||||||
<version>${org.mapstruct.version}</version>
|
<version>${mapstruct.version}</version>
|
||||||
</path>
|
</path>
|
||||||
<path>
|
<path>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>${org.projectlombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
</path>
|
</path>
|
||||||
</annotationProcessorPaths>
|
</annotationProcessorPaths>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -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:
|
spring:
|
||||||
|
application:
|
||||||
|
name: dashboard
|
||||||
# 数据源配置项 TODO 多数据源;TODO 监控配置
|
# 数据源配置项 TODO 多数据源;TODO 监控配置
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:mysql://127.0.1:3306/ruoyi-vue-pro?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
|
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:
|
security:
|
||||||
token-header: Authorization
|
token-header: Authorization
|
||||||
token-secret: abcdefghijklmnopqrstuvwxyz
|
token-secret: abcdefghijklmnopqrstuvwxyz
|
||||||
token-expires: 30m
|
token-timeout: 1d
|
||||||
|
session-timeout: 30m
|
||||||
swagger:
|
swagger:
|
||||||
title: 管理后台
|
title: 管理后台
|
||||||
description: 提供管理员管理的所有功能
|
description: 提供管理员管理的所有功能
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
base-package: cn.iocoder.dashboard.modules
|
base-package: cn.iocoder.dashboard.modules
|
||||||
|
captcha:
|
||||||
|
timeout: 5m
|
||||||
|
width: 160
|
||||||
|
height: 60
|
||||||
|
Loading…
Reference in New Issue
Block a user