From 4e5138fdfd60edf0d67787582905dfcc0801d667 Mon Sep 17 00:00:00 2001
From: zyy <zyy@email.com>
Date: Thu, 20 Nov 2025 17:38:10 +0800
Subject: [PATCH] 多ip地址登录
---
trading-order-admin/src/main/java/com/yami/trading/admin/controller/AdminLoginController.java | 12 +++++++++---
trading-order-security-common/src/main/java/com/yami/trading/security/common/filter/AuthFilter.java | 18 ++++++++++--------
trading-order-common/src/main/java/com/yami/trading/common/util/RedisUtil.java | 21 +++++++++++++++++----
trading-order-security-common/src/main/java/com/yami/trading/security/common/bo/UserInfoInTokenBO.java | 7 ++++++-
trading-order-common/src/main/java/com/yami/trading/common/constants/RedisKeys.java | 2 +-
5 files changed, 43 insertions(+), 17 deletions(-)
diff --git a/trading-order-admin/src/main/java/com/yami/trading/admin/controller/AdminLoginController.java b/trading-order-admin/src/main/java/com/yami/trading/admin/controller/AdminLoginController.java
index 6f8121d..99aa013 100644
--- a/trading-order-admin/src/main/java/com/yami/trading/admin/controller/AdminLoginController.java
+++ b/trading-order-admin/src/main/java/com/yami/trading/admin/controller/AdminLoginController.java
@@ -122,12 +122,18 @@
userInfoInToken.setPerms(getUserPermissions(sysUser.getUserId()));
userInfoInToken.setNickName(sysUser.getUsername());
userInfoInToken.setShopId(sysUser.getShopId());
- tokenStore.deleteAllToken(String.valueOf(SysTypeEnum.ADMIN.value()), String.valueOf(sysUser.getUserId()));
+ //tokenStore.deleteAllToken(String.valueOf(SysTypeEnum.ADMIN.value()), String.valueOf(sysUser.getUserId()));
// 存储token返回vo
TokenInfoVO tokenInfoVO = tokenStore.storeAndGetVo(userInfoInToken);
- RedisUtil.set(RedisKeys.ACCESS_IP + sysUser.getUserId().intValue(),IPHelper.getIpAddr());
-
+ //RedisUtil.set(RedisKeys.ACCESS_IP + sysUser.getUserId().intValue(),IPHelper.getIpAddr());
+ // 关键修改2:用Redis Set存储多个登录IP(自动去重)
+ String loginIp = IPHelper.getIpAddr();
+ String ipSetKey = RedisKeys.ACCESS_IP + sysUser.getUserId().intValue(); // 键:ACCESS_IP+用户ID
+ long tokenExpiresIn = tokenInfoVO.getExpiresIn(); // 与Token过期时间一致
+ RedisUtil.sAdd(ipSetKey, loginIp); // 存入IP到Set
+ RedisUtil.expire(ipSetKey, tokenExpiresIn); // 设置过期时间
+
String context = MessageFormat.format("ip:{0}, 登录系统,时间[{1}]",
new Object[]{IPHelper.getIpAddr(),
DateUtils.dateToStr(new Date(),
diff --git a/trading-order-common/src/main/java/com/yami/trading/common/constants/RedisKeys.java b/trading-order-common/src/main/java/com/yami/trading/common/constants/RedisKeys.java
index c083d5f..d775f8c 100644
--- a/trading-order-common/src/main/java/com/yami/trading/common/constants/RedisKeys.java
+++ b/trading-order-common/src/main/java/com/yami/trading/common/constants/RedisKeys.java
@@ -2,7 +2,7 @@
public class RedisKeys {
- public final static String ACCESS_IP = "ACCESS_IP";
+ public final static String ACCESS_IP = "NEW_ACCESS_IP";
/**
* item杠杆倍数
diff --git a/trading-order-common/src/main/java/com/yami/trading/common/util/RedisUtil.java b/trading-order-common/src/main/java/com/yami/trading/common/util/RedisUtil.java
index d45c0ee..9fb4139 100644
--- a/trading-order-common/src/main/java/com/yami/trading/common/util/RedisUtil.java
+++ b/trading-order-common/src/main/java/com/yami/trading/common/util/RedisUtil.java
@@ -7,11 +7,9 @@
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
/**
* @author lh
@@ -263,4 +261,19 @@
return retList;
}
+ // 向Set中添加元素(用于存储登录IP)
+ public static Long sAdd(String key, String value) {
+ return redisTemplate.opsForSet().add(key, value);
+ }
+
+ // 获取Set中的所有元素(用于获取已授权IP列表)- 兼容Java 8
+ public static Set<String> sMembers(String key) {
+ Set<Object> objectSet = redisTemplate.opsForSet().members(key);
+ if (CollectionUtil.isEmpty(objectSet)) {
+ // 替换 Set.of() 为 new HashSet<>()(Java 8支持)
+ return new HashSet<>();
+ }
+ // 转换为String类型Set
+ return objectSet.stream().map(String::valueOf).collect(Collectors.toSet());
+ }
}
diff --git a/trading-order-security-common/src/main/java/com/yami/trading/security/common/bo/UserInfoInTokenBO.java b/trading-order-security-common/src/main/java/com/yami/trading/security/common/bo/UserInfoInTokenBO.java
index ee22b47..4576b1d 100644
--- a/trading-order-security-common/src/main/java/com/yami/trading/security/common/bo/UserInfoInTokenBO.java
+++ b/trading-order-security-common/src/main/java/com/yami/trading/security/common/bo/UserInfoInTokenBO.java
@@ -12,6 +12,7 @@
import com.yami.trading.security.common.enums.SysTypeEnum;
import lombok.Data;
+import java.io.Serializable;
import java.util.Set;
/**
@@ -21,7 +22,8 @@
* @date 2022/3/25 17:33
*/
@Data
-public class UserInfoInTokenBO {
+public class UserInfoInTokenBO implements Serializable { // 新增:实现Serializable接口
+ private static final long serialVersionUID = 1L;
/**
* 用户在自己系统的用户id
@@ -66,4 +68,7 @@
*/
private Long otherId;
+ // 新增:无参构造函数(Jackson序列化必须,Lombok @Data不默认生成)
+ public UserInfoInTokenBO() {}
+
}
diff --git a/trading-order-security-common/src/main/java/com/yami/trading/security/common/filter/AuthFilter.java b/trading-order-security-common/src/main/java/com/yami/trading/security/common/filter/AuthFilter.java
index 7486460..3e94f38 100644
--- a/trading-order-security-common/src/main/java/com/yami/trading/security/common/filter/AuthFilter.java
+++ b/trading-order-security-common/src/main/java/com/yami/trading/security/common/filter/AuthFilter.java
@@ -3,10 +3,7 @@
import java.io.IOException;
import java.net.URLDecoder;
import java.time.ZoneId;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.Filter;
@@ -203,10 +200,15 @@
// 如果有 token,并且解析成功,则走以下处理逻辑
if (userInfoInToken.getSysType().intValue() == SysTypeEnum.ADMIN.value().intValue()) {
if (!pathMatcher.match("/updateCheckIp", requestUri)) {
- Object loginIP = RedisUtil.get(RedisKeys.ACCESS_IP + userInfoInToken.getUserId());
- if (null != loginIP && !IPHelper.equalIpSegment(loginIP.toString(), clientIp)) {
- logger.error("The Login IP Is Inconsistent With The Operation IP! Login-IP:{} Access-IP:{} Servlet-Path:{}", loginIP, clientIp, servletPath);
- httpHandler.printServerResponseToWeb("", 1001);
+ String ipSetKey = RedisKeys.ACCESS_IP + userInfoInToken.getUserId();
+ // 从Redis Set中获取该用户所有已授权登录IP
+ Set<String> authorizedIpSet = RedisUtil.sMembers(ipSetKey);
+
+ // 校验逻辑:已授权IP列表不为空,且当前IP在列表中
+ if (CollectionUtil.isEmpty(authorizedIpSet) || !authorizedIpSet.contains(clientIp)) {
+ logger.error("The Operation IP Is Not Authorized! Authorized-IPs:{}, Access-IP:{}, Servlet-Path:{}",
+ authorizedIpSet, clientIp, servletPath);
+ httpHandler.printServerResponseToWeb("当前IP未授权,请使用已登录设备访问或重新登录", 1001);
return;
}
}
--
Gitblit v1.9.3