From 6faeafcf68f1853f1ddb044916cb3d70bb63b332 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Tue, 2 Dec 2025 12:42:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=BB=E7=BB=93=E8=B4=A6=E5=8F=B7=E8=A7=A3?= =?UTF-8?q?=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datacenter/admin/common/Constants.java | 3 ++ .../admin/controller/UserController.java | 13 +++++++ .../datacenter/admin/service/UserService.java | 3 +- .../admin/service/impl/UserServiceImpl.java | 36 ++++++++++++++++++- .../admin/util/redis/RedisSentinelConfig.java | 23 ++++++++++++ .../util/redis/RedisStandaloneConfig.java | 23 ++++++++++++ 6 files changed, 99 insertions(+), 2 deletions(-) diff --git a/dongjian-center-admin-common/src/main/java/com/dongjian/datacenter/admin/common/Constants.java b/dongjian-center-admin-common/src/main/java/com/dongjian/datacenter/admin/common/Constants.java index edcaff3..cf33305 100644 --- a/dongjian-center-admin-common/src/main/java/com/dongjian/datacenter/admin/common/Constants.java +++ b/dongjian-center-admin-common/src/main/java/com/dongjian/datacenter/admin/common/Constants.java @@ -15,6 +15,9 @@ public class Constants { public static final String LOGIN_FAIL = APP_NAME + "login_fail:%s";// 失败次数,过期时间为1小时 public static final String LOGIN_LOCK = APP_NAME + "login_lock:%s";// 锁定标志,值为 true,过期时间为1小时 + public static final String BUSINESS_LOGIN_FAIL = "data-center-aeon:" + "login_fail:%s";// 失败次数,过期时间为1小时 + public static final String BUSINESS_LOGIN_LOCK = "data-center-aeon:" + "login_lock:%s";// 锁定标志,值为 true,过期时间为1小时 + //用户ID,登录名,企业ID,token public static final String ACCESS_TOKEN_FORMAT = APP_NAME + "RequestHeader:AccessToken:{0}:{1}:{2}:{3}"; diff --git a/dongjian-center-admin-controller/src/main/java/com/dongjian/datacenter/admin/controller/UserController.java b/dongjian-center-admin-controller/src/main/java/com/dongjian/datacenter/admin/controller/UserController.java index 312876f..b12139f 100644 --- a/dongjian-center-admin-controller/src/main/java/com/dongjian/datacenter/admin/controller/UserController.java +++ b/dongjian-center-admin-controller/src/main/java/com/dongjian/datacenter/admin/controller/UserController.java @@ -149,5 +149,18 @@ public class UserController { } return pageResponse; } + + @AccessRequired + @Operation(summary = "解除锁定") + @RequestMapping(value = "/batchUnlock",method = RequestMethod.POST) + public SimpleDataResponse batchUnlock( + @RequestBody ResetPassword userInfo, + @Parameter(name = "LoginName", description = "Login name", required = true, schema = @Schema(defaultValue = "admin")) @RequestHeader(required=true) String LoginName, + @Parameter(name = "AccessToken", description = "Authentication token", required = true) @RequestHeader(required=true) String AccessToken, + @Parameter(name = "UserId", description = "User ID", required = true, schema = @Schema(defaultValue = "1")) @RequestHeader(required=true) Long UserId, + @Parameter(name = "CompanyId", description = "ID of the company to which the user belongs", required = false, schema = @Schema(defaultValue = "1")) @RequestHeader(required=true) Long CompanyId, + @Parameter(name = "LanguageType", description = "Language type (0: Chinese, 1: English, 2: Japanese)", required = true, schema = @Schema(defaultValue = "2")) @RequestHeader(required=true) Integer LanguageType){ + return userService.batchUnlock(userInfo, CompanyId, UserId, LanguageType); + } } diff --git a/dongjian-center-admin-service/src/main/java/com/dongjian/datacenter/admin/service/UserService.java b/dongjian-center-admin-service/src/main/java/com/dongjian/datacenter/admin/service/UserService.java index aaa5f93..d0db32e 100644 --- a/dongjian-center-admin-service/src/main/java/com/dongjian/datacenter/admin/service/UserService.java +++ b/dongjian-center-admin-service/src/main/java/com/dongjian/datacenter/admin/service/UserService.java @@ -29,5 +29,6 @@ public interface UserService { SimpleDataResponse modifyPassword(ModifyPassword modifyPassword, Long companyId, Long userId, Integer languageType); SimpleDataResponse unbindMfa(SwitchMfaBind switchMfaBind, Long companyId, Long userId, Integer languageType); - + + SimpleDataResponse batchUnlock(ResetPassword userInfo, Long companyId, Long userId, Integer languageType); } diff --git a/dongjian-center-admin-service/src/main/java/com/dongjian/datacenter/admin/service/impl/UserServiceImpl.java b/dongjian-center-admin-service/src/main/java/com/dongjian/datacenter/admin/service/impl/UserServiceImpl.java index 216c720..ecf23a0 100644 --- a/dongjian-center-admin-service/src/main/java/com/dongjian/datacenter/admin/service/impl/UserServiceImpl.java +++ b/dongjian-center-admin-service/src/main/java/com/dongjian/datacenter/admin/service/impl/UserServiceImpl.java @@ -1,5 +1,6 @@ package com.dongjian.datacenter.admin.service.impl; +import com.dongjian.datacenter.admin.common.Constants; import com.github.pagehelper.PageHelper; import com.dongjian.datacenter.admin.common.exception.MsgCodeException; import com.dongjian.datacenter.admin.common.language.msg.MsgLanguageChange; @@ -30,6 +31,7 @@ import com.dongjian.datacenter.admin.util.async.OptAsync; import com.dongjian.datacenter.admin.util.redis.RedisUtil; import com.dongjian.datacenter.admin.vo.user.UserPageDTO; +import java.io.Serializable; import java.text.MessageFormat; import java.util.Arrays; import java.util.List; @@ -44,7 +46,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.TransactionAspectSupport; @@ -56,7 +60,10 @@ public class UserServiceImpl implements UserService { //同时含大写字母、小写字母、数字和特殊字符且长度大于8 private static final String pwdPattern = "^(?=.*\\d)(?=.*[a-zA-Z])(?=.*[~!@#$%^&*])[\\da-zA-Z~!@#$%^&*]{12,}$"; - + + @Autowired + @Qualifier("redisTemplateForBusiness") + private RedisTemplate redisTemplateForBusiness; @Value("${web.login.url}") private String webLoginUrl; @@ -420,5 +427,32 @@ public class UserServiceImpl implements UserService { return new SimpleDataResponse(ResponseCode.SERVER_ERROR, e.getMessage()); } } + + @Override + public SimpleDataResponse batchUnlock(ResetPassword userInfo, Long companyId, Long userId, Integer languageType) { + if (StringUtils.isBlank(userInfo.getUserIds())) { + return SimpleDataResponse.success(); + } + try { + List idList = Arrays.asList(userInfo.getUserIds().split(",")).stream().map(s -> Long.parseLong(s.trim())).collect(Collectors.toList()); + + for (Long targetUserId : idList) { + String lockKey = String.format(Constants.LOGIN_LOCK, targetUserId); + String failKey = String.format(Constants.LOGIN_FAIL, targetUserId); + redisTemplateForBusiness.delete(lockKey); + redisTemplateForBusiness.delete(failKey); + + String businessLockKey = String.format(Constants.BUSINESS_LOGIN_LOCK, targetUserId); + String businessFailKey = String.format(Constants.BUSINESS_LOGIN_FAIL, targetUserId); + redisTemplateForBusiness.delete(businessLockKey); + redisTemplateForBusiness.delete(businessFailKey); + } + + return SimpleDataResponse.success(); + } catch (Exception e) { + logger.error("batchUnlock error", e); + return new SimpleDataResponse(ResponseCode.SERVER_ERROR, "server error"); + } + } } diff --git a/dongjian-center-admin-util/src/main/java/com/dongjian/datacenter/admin/util/redis/RedisSentinelConfig.java b/dongjian-center-admin-util/src/main/java/com/dongjian/datacenter/admin/util/redis/RedisSentinelConfig.java index 7762093..0ba45df 100644 --- a/dongjian-center-admin-util/src/main/java/com/dongjian/datacenter/admin/util/redis/RedisSentinelConfig.java +++ b/dongjian-center-admin-util/src/main/java/com/dongjian/datacenter/admin/util/redis/RedisSentinelConfig.java @@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisConfiguration; import org.springframework.data.redis.connection.RedisPassword; import org.springframework.data.redis.connection.RedisSentinelConfiguration; @@ -78,6 +79,7 @@ public class RedisSentinelConfig { } @Bean + @Primary public LettuceConnectionFactory lettuceConnectionFactory(RedisConfiguration redisConfiguration) { GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig(); genericObjectPoolConfig.setMaxIdle(maxIdle); @@ -107,4 +109,25 @@ public class RedisSentinelConfig { template.setConnectionFactory(redisConnectionFactory); return template; } + + @Bean(name = "redisTemplateForBusiness") + public RedisTemplate redisTemplateForBusiness() { + // 创建一个独立的 Redis 配置 + RedisSentinelConfiguration config = new RedisSentinelConfiguration(master, new HashSet<>(Arrays.asList(nodes.split(",")))); + config.setPassword(RedisPassword.of(password)); + config.setDatabase(0); // business使用数据库0 + + // 创建一个连接工厂 + LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(config); + connectionFactory.start(); + + connectionFactory.setShareNativeConnection(false); // 交由自定义池控制 + RedisTemplate template = new RedisTemplate<>(); + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); // Hash key序列化 + template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); // Hash value序列化 + template.setConnectionFactory(connectionFactory); + return template; + } } \ No newline at end of file diff --git a/dongjian-center-admin-util/src/main/java/com/dongjian/datacenter/admin/util/redis/RedisStandaloneConfig.java b/dongjian-center-admin-util/src/main/java/com/dongjian/datacenter/admin/util/redis/RedisStandaloneConfig.java index 25b6800..acdeee5 100644 --- a/dongjian-center-admin-util/src/main/java/com/dongjian/datacenter/admin/util/redis/RedisStandaloneConfig.java +++ b/dongjian-center-admin-util/src/main/java/com/dongjian/datacenter/admin/util/redis/RedisStandaloneConfig.java @@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisConfiguration; import org.springframework.data.redis.connection.RedisPassword; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; @@ -75,6 +76,7 @@ public class RedisStandaloneConfig { } @Bean + @Primary public LettuceConnectionFactory lettuceConnectionFactory(RedisConfiguration redisConfiguration) { GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig(); genericObjectPoolConfig.setMaxIdle(maxIdle); @@ -103,4 +105,25 @@ public class RedisStandaloneConfig { template.setConnectionFactory(redisConnectionFactory); return template; } + + @Bean(name = "redisTemplateForBusiness") + public RedisTemplate redisTemplateForBusiness() { + RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); + config.setHostName(host); + config.setPort(port); + config.setPassword(RedisPassword.of(password)); + config.setDatabase(0); // business使用数据库0 + + LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(config); + connectionFactory.start(); + + connectionFactory.setShareNativeConnection(false); // 交由定义池控制 + RedisTemplate template = new RedisTemplate<>(); + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); // Hash key序列化 + template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); // Hash value序列化 + template.setConnectionFactory(connectionFactory); + return template; + } } \ No newline at end of file