mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-27 01:32:03 +08:00
优化图片验证码的后端实现
This commit is contained in:
parent
020535ab3a
commit
926c75d29a
@ -12,8 +12,8 @@
|
|||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
<description>
|
<description>验证码拓展
|
||||||
验证码
|
1. 基于 aj-captcha 实现图形验证码,文档:https://ajcaptcha.beliefteam.cn/captcha-doc/
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -23,9 +23,10 @@
|
|||||||
<artifactId>spring-boot-starter</artifactId>
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- DB 相关 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.iocoder.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>yudao-spring-boot-starter-redis</artifactId>
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 验证码相关 -->
|
<!-- 验证码相关 -->
|
||||||
@ -33,7 +34,6 @@
|
|||||||
<groupId>com.anji-plus</groupId>
|
<groupId>com.anji-plus</groupId>
|
||||||
<artifactId>spring-boot-starter-captcha</artifactId>
|
<artifactId>spring-boot-starter-captcha</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package cn.iocoder.yudao.framework.captcha.config;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ClassUtil;
|
||||||
|
import cn.iocoder.yudao.framework.captcha.core.enums.CaptchaRedisKeyConstants;
|
||||||
|
import cn.iocoder.yudao.framework.captcha.core.service.RedisCaptchaServiceImpl;
|
||||||
|
import com.anji.captcha.service.CaptchaCacheService;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class YudaoCaptchaConfiguration {
|
||||||
|
|
||||||
|
static {
|
||||||
|
// 手动加载 Lock4jRedisKeyConstants 类,因为它不会被使用到
|
||||||
|
// 如果不加载,会导致 Redis 监控,看到它的 Redis Key 枚举
|
||||||
|
ClassUtil.loadClass(CaptchaRedisKeyConstants.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CaptchaCacheService captchaCacheService(StringRedisTemplate stringRedisTemplate) {
|
||||||
|
return new RedisCaptchaServiceImpl(stringRedisTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,23 +1,31 @@
|
|||||||
package cn.iocoder.yudao.captcha.core.service;
|
package cn.iocoder.yudao.framework.captcha.core.service;
|
||||||
|
|
||||||
import com.anji.captcha.service.CaptchaCacheService;
|
import com.anji.captcha.service.CaptchaCacheService;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Service
|
/**
|
||||||
public class CaptchaServiceImpl implements CaptchaCacheService {
|
* 基于 Redis 实现验证码的存储
|
||||||
|
*
|
||||||
|
* @author 星语
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor // 保证 aj-captcha 的 SPI 创建
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class RedisCaptchaServiceImpl implements CaptchaCacheService {
|
||||||
|
|
||||||
|
@Resource // 保证 aj-captcha 的 SPI 创建时的注入
|
||||||
|
private StringRedisTemplate stringRedisTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String type() {
|
public String type() {
|
||||||
return "redis";
|
return "redis";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Resource
|
|
||||||
private StringRedisTemplate stringRedisTemplate;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void set(String key, String value, long expiresInSeconds) {
|
public void set(String key, String value, long expiresInSeconds) {
|
||||||
stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
|
stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
|
||||||
@ -42,4 +50,5 @@ public class CaptchaServiceImpl implements CaptchaCacheService {
|
|||||||
public Long increment(String key, long val) {
|
public Long increment(String key, long val) {
|
||||||
return stringRedisTemplate.opsForValue().increment(key,val);
|
return stringRedisTemplate.opsForValue().increment(key,val);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* 验证码拓展
|
||||||
|
* 1. 基于 aj-captcha 实现图形验证码,文档:https://ajcaptcha.beliefteam.cn/captcha-doc/
|
||||||
|
*
|
||||||
|
* @author 星语
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.framework.captcha;
|
@ -1 +1 @@
|
|||||||
cn.iocoder.yudao.captcha.core.service.CaptchaServiceImpl
|
cn.iocoder.yudao.framework.captcha.core.service.RedisCaptchaServiceImpl
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
|
cn.iocoder.yudao.framework.captcha.config.YudaoCaptchaConfiguration
|
@ -12,8 +12,7 @@ public interface ErrorCodeConstants {
|
|||||||
// ========== AUTH 模块 1002000000 ==========
|
// ========== AUTH 模块 1002000000 ==========
|
||||||
ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确");
|
ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确");
|
||||||
ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用");
|
ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用");
|
||||||
ErrorCode AUTH_LOGIN_CAPTCHA_NOT_FOUND = new ErrorCode(1002000003, "验证码不存在");
|
ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确,原因:{}");
|
||||||
ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确");
|
|
||||||
ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1002000005, "未绑定账号,需要进行绑定");
|
ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1002000005, "未绑定账号,需要进行绑定");
|
||||||
ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1002000006, "Token 已经过期");
|
ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1002000006, "Token 已经过期");
|
||||||
ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1002000007, "手机号不存在");
|
ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1002000007, "手机号不存在");
|
||||||
|
@ -33,8 +33,10 @@ public class AuthLoginReqVO {
|
|||||||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@ApiModelProperty(value = "验证码", required = true, example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
|
@ApiModelProperty(value = "验证码", required = true,
|
||||||
@NotEmpty(message = "验证码不能为空")
|
example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==",
|
||||||
|
notes = "验证码开启时,需要传递")
|
||||||
|
@NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
|
||||||
private String captchaVerification;
|
private String captchaVerification;
|
||||||
|
|
||||||
// ========== 绑定社交登录时,需要传递如下参数 ==========
|
// ========== 绑定社交登录时,需要传递如下参数 ==========
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.system.framework.captcha.config;
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableConfigurationProperties(CaptchaProperties.class)
|
|
||||||
public class CaptchaConfig {
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.system.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 {
|
|
||||||
|
|
||||||
private static final Boolean ENABLE_DEFAULT = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否开启
|
|
||||||
* 注意,这里仅仅是后端 Server 是否校验,暂时不控制前端的逻辑
|
|
||||||
*/
|
|
||||||
private Boolean enable = ENABLE_DEFAULT;
|
|
||||||
/**
|
|
||||||
* 验证码的过期时间
|
|
||||||
*/
|
|
||||||
@NotNull(message = "验证码的过期时间不为空")
|
|
||||||
private Duration timeout;
|
|
||||||
/**
|
|
||||||
* 验证码的高度
|
|
||||||
*/
|
|
||||||
@NotNull(message = "验证码的高度不能为空")
|
|
||||||
private Integer height;
|
|
||||||
/**
|
|
||||||
* 验证码的宽度
|
|
||||||
*/
|
|
||||||
@NotNull(message = "验证码的宽度不能为空")
|
|
||||||
private Integer width;
|
|
||||||
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
/**
|
|
||||||
* 基于 Hutool captcha 库,实现验证码功能
|
|
||||||
*/
|
|
||||||
package cn.iocoder.yudao.module.system.framework.captcha;
|
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|||||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||||
import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
|
import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
|
||||||
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
|
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
|
||||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
|
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||||
@ -24,7 +25,9 @@ import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
|||||||
import com.anji.captcha.model.common.ResponseModel;
|
import com.anji.captcha.model.common.ResponseModel;
|
||||||
import com.anji.captcha.model.vo.CaptchaVO;
|
import com.anji.captcha.model.vo.CaptchaVO;
|
||||||
import com.anji.captcha.service.CaptchaService;
|
import com.anji.captcha.service.CaptchaService;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@ -61,6 +64,12 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
|||||||
@Resource
|
@Resource
|
||||||
private SmsCodeApi smsCodeApi;
|
private SmsCodeApi smsCodeApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码的开关,默认为 true
|
||||||
|
*/
|
||||||
|
@Value("${yudao.captcha.enable:true}")
|
||||||
|
private Boolean captchaEnable;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AdminUserDO authenticate(String username, String password) {
|
public AdminUserDO authenticate(String username, String password) {
|
||||||
final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME;
|
final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME;
|
||||||
@ -84,23 +93,19 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthLoginRespVO login(AuthLoginReqVO reqVO) {
|
public AuthLoginRespVO login(AuthLoginReqVO reqVO) {
|
||||||
CaptchaVO captchaVO = new CaptchaVO();
|
// 校验验证码
|
||||||
captchaVO.setCaptchaVerification(reqVO.getCaptchaVerification());
|
verifyCaptcha(reqVO);
|
||||||
ResponseModel response = captchaService.verification(captchaVO);
|
|
||||||
if(response.isSuccess()){
|
|
||||||
// 使用账号密码,进行登录
|
|
||||||
AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
|
|
||||||
|
|
||||||
// 如果 socialType 非空,说明需要绑定社交用户
|
// 使用账号密码,进行登录
|
||||||
if (reqVO.getSocialType() != null) {
|
AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
|
||||||
socialUserService.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
|
|
||||||
reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
|
// 如果 socialType 非空,说明需要绑定社交用户
|
||||||
}
|
if (reqVO.getSocialType() != null) {
|
||||||
// 创建 Token 令牌,记录登录日志
|
socialUserService.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
|
||||||
return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
|
reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
|
||||||
}else{
|
|
||||||
throw exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR);
|
|
||||||
}
|
}
|
||||||
|
// 创建 Token 令牌,记录登录日志
|
||||||
|
return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -172,6 +177,25 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
|||||||
return AuthConvert.INSTANCE.convert(accessTokenDO);
|
return AuthConvert.INSTANCE.convert(accessTokenDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void verifyCaptcha(AuthLoginReqVO reqVO) {
|
||||||
|
// 如果验证码关闭,则不进行校验
|
||||||
|
if (!captchaEnable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 校验验证码
|
||||||
|
ValidationUtils.validate(validator, reqVO, AuthLoginReqVO.CodeEnableGroup.class);
|
||||||
|
CaptchaVO captchaVO = new CaptchaVO();
|
||||||
|
captchaVO.setCaptchaVerification(reqVO.getCaptchaVerification());
|
||||||
|
ResponseModel response = captchaService.verification(captchaVO);
|
||||||
|
// 验证不通过
|
||||||
|
if (!response.isSuccess()) {
|
||||||
|
// 创建登录失败日志(验证码不正确)
|
||||||
|
createLoginLog(null, reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.CAPTCHA_CODE_ERROR);
|
||||||
|
throw exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR, response.getRepMsg());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private AuthLoginRespVO createTokenAfterLoginSuccess(Long userId, String username, LoginLogTypeEnum logType) {
|
private AuthLoginRespVO createTokenAfterLoginSuccess(Long userId, String username, LoginLogTypeEnum logType) {
|
||||||
// 插入登陆日志
|
// 插入登陆日志
|
||||||
createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
|
createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
|
||||||
|
@ -61,38 +61,20 @@ mybatis-plus:
|
|||||||
|
|
||||||
aj:
|
aj:
|
||||||
captcha:
|
captcha:
|
||||||
# 滑动验证,底图路径,不配置将使用默认图片
|
jigsaw: classpath:images/jigsaw # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径
|
||||||
# 支持全路径
|
pic-click: classpath:images/pic-click # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径
|
||||||
# 支持项目路径,以classpath:开头,取resource目录下路径,例:classpath:images/jigsaw
|
cache-type: redis # 缓存 local/redis...
|
||||||
jigsaw: classpath:images/jigsaw
|
cache-number: 1000 # local 缓存的阈值,达到这个值,清除缓存
|
||||||
#滑动验证,底图路径,不配置将使用默认图片
|
timing-clear: 180 # local定时清除过期缓存(单位秒),设置为0代表不执行
|
||||||
##支持全路径
|
type: blockPuzzle # 验证码类型 default两种都实例化。 blockPuzzle 滑块拼图 clickWord 文字点选
|
||||||
# 支持项目路径,以classpath:开头,取resource目录下路径,例:classpath:images/pic-click
|
water-mark: 芋道源码 # 右下角水印文字(我的水印),可使用 https://tool.chinaz.com/tools/unicode.aspx 中文转 Unicode,Linux 可能需要转 unicode
|
||||||
pic-click: classpath:images/pic-click
|
interference-options: 2 # 滑动干扰项(0/1/2)
|
||||||
# 缓存local/redis...
|
req-frequency-limit-enable: false # 接口请求次数一分钟限制是否开启 true|false
|
||||||
cache-type: redis
|
req-get-lock-limit: 5 # 验证失败5次,get接口锁定
|
||||||
# local缓存的阈值,达到这个值,清除缓存
|
req-get-lock-seconds: 10 # 验证失败后,锁定时间间隔
|
||||||
cache-number: 1000
|
req-get-minute-limit: 30 # get 接口一分钟内请求数限制
|
||||||
# local定时清除过期缓存(单位秒),设置为0代表不执行
|
req-check-minute-limit: 60 # check 接口一分钟内请求数限制
|
||||||
timing-clear: 180
|
req-verify-minute-limit: 60 # verify 接口一分钟内请求数限制
|
||||||
# 验证码类型 default两种都实例化。 blockPuzzle 滑块拼图 clickWord 文字点选
|
|
||||||
type: blockPuzzle
|
|
||||||
# 右下角水印文字(我的水印)https://tool.chinaz.com/tools/unicode.aspx 中文转Unicode Linux可能需要转unicode
|
|
||||||
water-mark: 芋道源码
|
|
||||||
# 滑动干扰项(0/1/2)
|
|
||||||
interference-options: 2
|
|
||||||
# 接口请求次数一分钟限制是否开启 true|false
|
|
||||||
req-frequency-limit-enable: true
|
|
||||||
# 验证失败5次,get接口锁定
|
|
||||||
req-get-lock-limit: 5
|
|
||||||
# 验证失败后,锁定时间间隔,s
|
|
||||||
req-get-lock-seconds: 10
|
|
||||||
# get接口一分钟内请求数限制
|
|
||||||
req-get-minute-limit: 30
|
|
||||||
# check接口一分钟内请求数限制
|
|
||||||
req-check-minute-limit: 60
|
|
||||||
# verify接口一分钟内请求数限制
|
|
||||||
req-verify-minute-limit: 60
|
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
||||||
@ -112,9 +94,7 @@ yudao:
|
|||||||
version: ${yudao.info.version}
|
version: ${yudao.info.version}
|
||||||
base-package: ${yudao.info.base-package}
|
base-package: ${yudao.info.base-package}
|
||||||
captcha:
|
captcha:
|
||||||
timeout: 5m
|
enable: true # 验证码的开关,默认为 true;注意,优先读取数据库 infra_config 的 yudao.captcha.enable,所以请从数据库修改,可能需要重启项目
|
||||||
width: 160
|
|
||||||
height: 60
|
|
||||||
codegen:
|
codegen:
|
||||||
base-package: ${yudao.info.base-package}
|
base-package: ${yudao.info.base-package}
|
||||||
db-schemas: ${spring.datasource.dynamic.datasource.master.name}
|
db-schemas: ${spring.datasource.dynamic.datasource.master.name}
|
||||||
@ -134,8 +114,7 @@ yudao:
|
|||||||
- /admin-api/infra/file/*/get/** # 获取图片,和租户无关
|
- /admin-api/infra/file/*/get/** # 获取图片,和租户无关
|
||||||
- /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号
|
- /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号
|
||||||
- /app-api/pay/order/notify/* # 支付回调通知,不携带租户编号
|
- /app-api/pay/order/notify/* # 支付回调通知,不携带租户编号
|
||||||
# - /jmreport/list
|
- /jmreport/* # 积木报表,无法携带租户编号
|
||||||
- /jmreport/*
|
|
||||||
ignore-tables:
|
ignore-tables:
|
||||||
- system_tenant
|
- system_tenant
|
||||||
- system_tenant_package
|
- system_tenant_package
|
||||||
|
Loading…
Reference in New Issue
Block a user