mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-14 02:55:07 +08:00
优化图片验证码的后端实现
This commit is contained in:
@ -33,8 +33,10 @@ public class AuthLoginReqVO {
|
||||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
|
||||
@ApiModelProperty(value = "验证码", required = true, example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
|
||||
@NotEmpty(message = "验证码不能为空")
|
||||
@ApiModelProperty(value = "验证码", required = true,
|
||||
example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==",
|
||||
notes = "验证码开启时,需要传递")
|
||||
@NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
|
||||
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.util.monitor.TracerUtils;
|
||||
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.sms.SmsCodeApi;
|
||||
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.vo.CaptchaVO;
|
||||
import com.anji.captcha.service.CaptchaService;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@ -61,6 +64,12 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
@Resource
|
||||
private SmsCodeApi smsCodeApi;
|
||||
|
||||
/**
|
||||
* 验证码的开关,默认为 true
|
||||
*/
|
||||
@Value("${yudao.captcha.enable:true}")
|
||||
private Boolean captchaEnable;
|
||||
|
||||
@Override
|
||||
public AdminUserDO authenticate(String username, String password) {
|
||||
final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME;
|
||||
@ -84,23 +93,19 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
|
||||
@Override
|
||||
public AuthLoginRespVO login(AuthLoginReqVO reqVO) {
|
||||
CaptchaVO captchaVO = new CaptchaVO();
|
||||
captchaVO.setCaptchaVerification(reqVO.getCaptchaVerification());
|
||||
ResponseModel response = captchaService.verification(captchaVO);
|
||||
if(response.isSuccess()){
|
||||
// 使用账号密码,进行登录
|
||||
AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
|
||||
// 校验验证码
|
||||
verifyCaptcha(reqVO);
|
||||
|
||||
// 如果 socialType 非空,说明需要绑定社交用户
|
||||
if (reqVO.getSocialType() != null) {
|
||||
socialUserService.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
|
||||
reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
|
||||
}
|
||||
// 创建 Token 令牌,记录登录日志
|
||||
return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
|
||||
}else{
|
||||
throw exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR);
|
||||
// 使用账号密码,进行登录
|
||||
AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
|
||||
|
||||
// 如果 socialType 非空,说明需要绑定社交用户
|
||||
if (reqVO.getSocialType() != null) {
|
||||
socialUserService.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
|
||||
reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
|
||||
}
|
||||
// 创建 Token 令牌,记录登录日志
|
||||
return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -172,6 +177,25 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
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) {
|
||||
// 插入登陆日志
|
||||
createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
|
||||
|
Reference in New Issue
Block a user