【新增】改进用户注销接口

This commit is contained in:
2025-12-12 11:44:56 +08:00
parent 8ac012f49c
commit c74505b8c3
6 changed files with 118 additions and 50 deletions

View File

@@ -210,8 +210,17 @@ public class AppUserController {
* @param logoffRequest * @param logoffRequest
* @return * @return
*/ */
@PostMapping("/logoff") @PostMapping("/delete")
public Result<String> logoff(@RequestBody @Valid LogoffRequest logoffRequest) { public Result<String> logoff(@RequestBody @Valid LogoffRequest logoffRequest) {
return Result.isBool(userService.logoff(logoffRequest)); return Result.isBool(userService.logoff(logoffRequest));
} }
/**
* 注销发送验证码
* @return
*/
@PostMapping("/delete/sendCode")
public Result<Map<String, String>> deleteSendCode() {
return userService.deleteSendCode();
}
} }

View File

@@ -2,6 +2,7 @@ package com.corewing.app.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.corewing.app.common.Result;
import com.corewing.app.dto.api.CodeLoginRequest; import com.corewing.app.dto.api.CodeLoginRequest;
import com.corewing.app.dto.api.ForgetPasswordRequest; import com.corewing.app.dto.api.ForgetPasswordRequest;
import com.corewing.app.dto.api.LogoffRequest; import com.corewing.app.dto.api.LogoffRequest;
@@ -9,6 +10,8 @@ import com.corewing.app.dto.biz.user.BizUserStatusRequest;
import com.corewing.app.dto.biz.user.ResetPasswordRequest; import com.corewing.app.dto.biz.user.ResetPasswordRequest;
import com.corewing.app.entity.User; import com.corewing.app.entity.User;
import java.util.Map;
/** /**
* 应用用户 Service 接口 * 应用用户 Service 接口
@@ -137,4 +140,10 @@ public interface UserService extends IService<User> {
* @return * @return
*/ */
boolean logoff(LogoffRequest logoffRequest); boolean logoff(LogoffRequest logoffRequest);
/**
* 删除发送验证码
* @return
*/
Result<Map<String, String>> deleteSendCode();
} }

View File

View File

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.corewing.app.common.Result;
import com.corewing.app.common.page.PageContext; import com.corewing.app.common.page.PageContext;
import com.corewing.app.dto.api.CodeLoginRequest; import com.corewing.app.dto.api.CodeLoginRequest;
import com.corewing.app.dto.api.ForgetPasswordRequest; import com.corewing.app.dto.api.ForgetPasswordRequest;
@@ -15,33 +16,44 @@ import com.corewing.app.entity.User;
import com.corewing.app.mapper.UserMapper; import com.corewing.app.mapper.UserMapper;
import com.corewing.app.service.UserService; import com.corewing.app.service.UserService;
import com.corewing.app.service.VerifyCodeService; import com.corewing.app.service.VerifyCodeService;
import com.corewing.app.util.I18nUtil; import com.corewing.app.util.*;
import com.corewing.app.util.Ip2RegionUtil; import lombok.extern.slf4j.Slf4j;
import com.corewing.app.util.RedisUtil; import org.codehaus.jettison.json.JSONObject;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils; import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
/** /**
* 应用用户 Service 实现类 * 应用用户 Service 实现类
*/ */
@Slf4j
@Service @Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
private final VerifyCodeService verifyCodeService; @Resource
private final Ip2RegionUtil ip2RegionUtil; private VerifyCodeService verifyCodeService;
private final UserMapper userMapper;
private final RedisUtil redisUtil; @Resource
private Ip2RegionUtil ip2RegionUtil;
@Resource
private UserMapper userMapper;
@Resource
private RedisUtil redisUtil;
@Resource
private SmsBaoUtil smsBaoUtil;
@Resource
private EmailUtil emailUtil;
public UserServiceImpl(VerifyCodeService verifyCodeService, Ip2RegionUtil ip2RegionUtil, UserMapper userMapper, RedisUtil redisUtil) {
this.verifyCodeService = verifyCodeService;
this.ip2RegionUtil = ip2RegionUtil;
this.userMapper = userMapper;
this.redisUtil = redisUtil;
}
@Override @Override
public Page<User> page(User user) { public Page<User> page(User user) {
@@ -304,19 +316,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
if(user == null) { if(user == null) {
throw new RuntimeException(I18nUtil.getMessage("error.user.not.found")); throw new RuntimeException(I18nUtil.getMessage("error.user.not.found"));
} }
String codeKey = ""; String codeKey = String.format("verify_code:%s:%s", "logoff", user.getUsername());
Object checkCode = null; Object checkCode = redisUtil.get(codeKey);
if(user.getEmail() != null) {
codeKey = String.format("verify_code:%s:%s", "logoff", user.getEmail());
checkCode = redisUtil.get(codeKey);
}
if(checkCode == null) {
if(user.getTelephone() != null) {
codeKey = String.format("verify_code:%s:%s", "logoff", user.getTelephone());
checkCode = redisUtil.get(codeKey);
}
}
if(checkCode == null || !request.getCode().equalsIgnoreCase(checkCode.toString())) { if(checkCode == null || !request.getCode().equalsIgnoreCase(checkCode.toString())) {
throw new RuntimeException(I18nUtil.getMessage("error.verify.code.invalid")); throw new RuntimeException(I18nUtil.getMessage("error.verify.code.invalid"));
@@ -327,4 +328,41 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
this.removeById(user.getId()); this.removeById(user.getId());
return true; return true;
} }
@Override
public Result<Map<String, String>> deleteSendCode() {
User user = this.getById(StpUtil.getLoginId().toString());
if(user == null) {
throw new RuntimeException(I18nUtil.getMessage("error.user.not.found"));
}
String code = CommonGenerateUtil.generateCode();
// 保存到 Rediskey格式verify_code:{type}:{account}
String redisKey = String.format("verify_code:%s:%s", "logoff", user.getUsername());
redisUtil.set(redisKey, code, CommonGenerateUtil.CODE_EXPIRE_MINUTES * 60);
log.info("验证码已生成: account={}, type={}, code={}", user.getUsername(), "logoff", code);
// 发送验证码
if (!StringUtils.hasText(user.getTelephone())) {
// 发送短信验证码
boolean success = smsBaoUtil.sendVerifyCode(user.getTelephone(), code);
if (!success) {
throw new RuntimeException(I18nUtil.getMessage("error.sms.send.failed"));
}
Map<String, String> map = new HashMap<>();
map.put("account", user.getTelephone());
return Result.success(map);
} else {
// 发送邮件验证码
boolean success = emailUtil.sendVerifyCode(user.getEmail(), code);
if (!success) {
throw new RuntimeException(I18nUtil.getMessage("error.email.send.failed"));
}
Map<String, String> map = new HashMap<>();
map.put("account", user.getEmail());
return Result.success(map);
}
}
} }

View File

@@ -19,15 +19,8 @@ public class VerifyCodeServiceImpl implements VerifyCodeService {
private final SmsBaoUtil smsBaoUtil; private final SmsBaoUtil smsBaoUtil;
private final EmailUtil emailUtil; private final EmailUtil emailUtil;
/**
* 验证码有效期(分钟)
*/
private static final int CODE_EXPIRE_MINUTES = 5;
/**
* 验证码长度
*/
private static final int CODE_LENGTH = 6;
public VerifyCodeServiceImpl(RedisUtil redisUtil, SmsBaoUtil smsBaoUtil, EmailUtil emailUtil) { public VerifyCodeServiceImpl(RedisUtil redisUtil, SmsBaoUtil smsBaoUtil, EmailUtil emailUtil) {
this.redisUtil = redisUtil; this.redisUtil = redisUtil;
@@ -50,11 +43,11 @@ public class VerifyCodeServiceImpl implements VerifyCodeService {
} }
// 生成验证码 // 生成验证码
String code = generateCode(); String code = CommonGenerateUtil.generateCode();
// 保存到 Rediskey格式verify_code:{type}:{account} // 保存到 Rediskey格式verify_code:{type}:{account}
String redisKey = String.format("verify_code:%s:%s", type, account); String redisKey = String.format("verify_code:%s:%s", type, account);
redisUtil.set(redisKey, code, CODE_EXPIRE_MINUTES * 60); redisUtil.set(redisKey, code, CommonGenerateUtil.CODE_EXPIRE_MINUTES * 60);
log.info("验证码已生成: account={}, type={}, code={}", account, type, code); log.info("验证码已生成: account={}, type={}, code={}", account, type, code);
@@ -106,17 +99,4 @@ public class VerifyCodeServiceImpl implements VerifyCodeService {
return matched; return matched;
} }
/**
* 生成随机验证码
*
* @return 验证码
*/
private String generateCode() {
Random random = new Random();
StringBuilder code = new StringBuilder();
for (int i = 0; i < CODE_LENGTH; i++) {
code.append(random.nextInt(10));
}
return code.toString();
}
} }

View File

@@ -0,0 +1,32 @@
package com.corewing.app.util;
import java.util.Random;
public class CommonGenerateUtil {
/**
* 验证码长度
*/
private static final int CODE_LENGTH = 6;
/**
* 验证码有效期(分钟)
*/
public static final int CODE_EXPIRE_MINUTES = 5;
/**
* 生成随机验证码
*
* @return 验证码
*/
public static String generateCode() {
Random random = new Random();
StringBuilder code = new StringBuilder();
for (int i = 0; i < CODE_LENGTH; i++) {
code.append(random.nextInt(10));
}
return code.toString();
}
}