From 8be178317ab12a2096beb12b1632a87a2edbf81a Mon Sep 17 00:00:00 2001 From: liulu Date: Thu, 2 Jan 2025 15:29:49 +0800 Subject: [PATCH] =?UTF-8?q?=E7=99=BD=E5=90=8D=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/IpWhitelistServiceImpl.java | 2 +- .../java/com/sunyard}/config/IpFilter.java | 4 +- .../serviceimpl/ParamConfServiceImpl.java | 14 ++---- .../com/sunyard/chsm/auth/AppTokenFilter.java | 47 +++++++++++++++++-- .../com/sunyard/chsm/pool/DeviceManager.java | 6 +++ .../sunyard/chsm/service/AppLoginService.java | 23 +++++++++ .../src/test/java/api/BaseTest.java | 7 ++- 7 files changed, 84 insertions(+), 19 deletions(-) rename {chsm-common/src/main/java/com/sunyard/chsm => chsm-web-manage/src/main/java/com/sunyard}/config/IpFilter.java (96%) diff --git a/chsm-web-manage/src/main/java/com/sunyard/chsm/service/impl/IpWhitelistServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/chsm/service/impl/IpWhitelistServiceImpl.java index f1abb51..8f9d287 100644 --- a/chsm-web-manage/src/main/java/com/sunyard/chsm/service/impl/IpWhitelistServiceImpl.java +++ b/chsm-web-manage/src/main/java/com/sunyard/chsm/service/impl/IpWhitelistServiceImpl.java @@ -4,13 +4,13 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.sunyard.chsm.config.IpFilter; import com.sunyard.chsm.dto.IpWhitelistDTO; import com.sunyard.chsm.enums.EnableStatus; import com.sunyard.chsm.mapper.IpWhitelisttMapper; import com.sunyard.chsm.model.entity.IpWhitelist; import com.sunyard.chsm.service.IpWhitelistService; import com.sunyard.chsm.utils.IpUtils; +import com.sunyard.config.IpFilter; import com.sunyard.ssp.utils.SecurityUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; diff --git a/chsm-common/src/main/java/com/sunyard/chsm/config/IpFilter.java b/chsm-web-manage/src/main/java/com/sunyard/config/IpFilter.java similarity index 96% rename from chsm-common/src/main/java/com/sunyard/chsm/config/IpFilter.java rename to chsm-web-manage/src/main/java/com/sunyard/config/IpFilter.java index b4d661d..8fab0aa 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/config/IpFilter.java +++ b/chsm-web-manage/src/main/java/com/sunyard/config/IpFilter.java @@ -1,4 +1,4 @@ -package com.sunyard.chsm.config; +package com.sunyard.config; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -53,7 +53,7 @@ public class IpFilter extends OncePerRequestFilter implements ApplicationRunner syncWhiteIps(); } String ip = IpUtils.getIpAddress(request); - if (!enableWhiteIp || CollectionUtils.isEmpty(whiteIps) || whiteIps.contains(ip)) { + if (!enableWhiteIp || whiteIps.contains(ip)) { chain.doFilter(request, response); return; } diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/serviceimpl/ParamConfServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/serviceimpl/ParamConfServiceImpl.java index 2c86825..11165cf 100644 --- a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/serviceimpl/ParamConfServiceImpl.java +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/serviceimpl/ParamConfServiceImpl.java @@ -2,10 +2,10 @@ package com.sunyard.ssp.modules.sysconf.paramconf.serviceimpl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.sunyard.chsm.config.IpFilter; import com.sunyard.chsm.mapper.ParamConfMapper; import com.sunyard.chsm.model.entity.ParamConf; import com.sunyard.chsm.service.IpWhitelistService; +import com.sunyard.config.IpFilter; import com.sunyard.ssp.modules.sysconf.paramconf.service.IParamConfService; import com.sunyard.ssp.modules.user.entity.ScPermission; import com.sunyard.ssp.modules.user.service.IScPermissionService; @@ -18,17 +18,9 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.TransactionAspectSupport; import java.time.LocalDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; +import java.util.*; -import static com.sunyard.chsm.constant.ParamConfKeyConstant.APPROVAL_TRUE; -import static com.sunyard.chsm.constant.ParamConfKeyConstant.AUTHORITY_APPROVAL_PARAM_ITEM; -import static com.sunyard.chsm.constant.ParamConfKeyConstant.ENCRYPTION_MACHINE_APPROVAL; -import static com.sunyard.chsm.constant.ParamConfKeyConstant.IP_WHITELIST_ITEM; -import static com.sunyard.chsm.constant.ParamConfKeyConstant.IP_WHITELIST_SWITCH; +import static com.sunyard.chsm.constant.ParamConfKeyConstant.*; import static com.sunyard.ssp.common.constant.CommonConstant.STATUS_DISABLE; import static com.sunyard.ssp.common.constant.CommonConstant.STATUS_NORMAL; diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/auth/AppTokenFilter.java b/chsm-web-server/src/main/java/com/sunyard/chsm/auth/AppTokenFilter.java index c096aa3..38f9a27 100644 --- a/chsm-web-server/src/main/java/com/sunyard/chsm/auth/AppTokenFilter.java +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/auth/AppTokenFilter.java @@ -1,15 +1,22 @@ package com.sunyard.chsm.auth; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.sunyard.chsm.enums.EnableStatus; +import com.sunyard.chsm.mapper.IpWhitelisttMapper; import com.sunyard.chsm.model.R; +import com.sunyard.chsm.model.entity.IpWhitelist; import com.sunyard.chsm.service.AppLoginService; +import com.sunyard.chsm.utils.IpUtils; import com.sunyard.chsm.utils.JsonUtils; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.JwtException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.web.filter.OncePerRequestFilter; @@ -18,9 +25,11 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.Enumeration; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import static com.sunyard.chsm.constant.SecurityConstant.ATTRIBUTE_APP_USER; @@ -32,7 +41,9 @@ import static com.sunyard.chsm.constant.SecurityConstant.ATTRIBUTE_APP_USER; @Slf4j @Component @RequiredArgsConstructor -public class AppTokenFilter extends OncePerRequestFilter { +public class AppTokenFilter extends OncePerRequestFilter implements InitializingBean { + + public static Map> WHITE_IP_MAP = new ConcurrentHashMap<>(); public static final Collection WHITE_URL = Arrays.asList( "/appUser/getAppToken", @@ -40,6 +51,7 @@ public class AppTokenFilter extends OncePerRequestFilter { ); private final AppLoginService appLoginService; + private final IpWhitelisttMapper ipWhitelisttMapper; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { @@ -58,6 +70,16 @@ public class AppTokenFilter extends OncePerRequestFilter { try { AppUser user = appLoginService.verifyToken(tokenValue); + List ips = WHITE_IP_MAP.getOrDefault(user.getAppId(), Collections.emptyList()); + String ip = IpUtils.getIpAddress(request); + if (!CollectionUtils.isEmpty(ips) && !ips.contains(ip)) { + logger.warn("forbidden for ip: " + ip); + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + response.setContentType(MediaType.TEXT_PLAIN_VALUE); + response.getWriter().println("this ip is forbidden"); + response.getWriter().flush(); + return; + } request.setAttribute(ATTRIBUTE_APP_USER, user); filterChain.doFilter(request, response); } catch (ExpiredJwtException ex) { @@ -110,4 +132,21 @@ public class AppTokenFilter extends OncePerRequestFilter { return null; } + @Override + public void afterPropertiesSet() throws ServletException { + super.afterPropertiesSet(); + + Executors.newSingleThreadScheduledExecutor() + .scheduleWithFixedDelay(() -> { + + List list = ipWhitelisttMapper.selectList( + new LambdaQueryWrapper() + .eq(IpWhitelist::getScope, "app") + .eq(IpWhitelist::getStatus, EnableStatus.ENABLED.getCode()) + ); + WHITE_IP_MAP = list.stream().collect(Collectors.groupingBy(IpWhitelist::getAppId, Collectors.mapping(IpWhitelist::getIp, Collectors.toList()))); + }, 1L, 5L, TimeUnit.MINUTES); + + } + } diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/pool/DeviceManager.java b/chsm-web-server/src/main/java/com/sunyard/chsm/pool/DeviceManager.java index c047ab2..85dccbf 100644 --- a/chsm-web-server/src/main/java/com/sunyard/chsm/pool/DeviceManager.java +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/pool/DeviceManager.java @@ -77,6 +77,12 @@ public class DeviceManager implements InitializingBean { if (atomicInteger.get() > Integer.MAX_VALUE - 10000) { atomicInteger.set(1); } + if (CollectionUtils.isEmpty(serviceDeviceMap)) { + log.warn("系统内没有可以设备..service Device is empty"); + TMKContext soft = getSoftContext(); + Assert.notNull(soft, "应用: " + user.getName() + "没有可用的密码设备"); + return soft; + } List contexts = serviceDeviceMap.entrySet().stream() .filter(it -> serviceIds.contains(it.getKey())) .map(Map.Entry::getValue) diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/service/AppLoginService.java b/chsm-web-server/src/main/java/com/sunyard/chsm/service/AppLoginService.java index 6c36508..f7c104b 100644 --- a/chsm-web-server/src/main/java/com/sunyard/chsm/service/AppLoginService.java +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/service/AppLoginService.java @@ -1,15 +1,19 @@ package com.sunyard.chsm.service; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.sunyard.chsm.auth.AppUser; import com.sunyard.chsm.constant.SecurityConstant; import com.sunyard.chsm.enums.EnableStatus; import com.sunyard.chsm.mapper.AppServiceMapper; import com.sunyard.chsm.mapper.ApplicationMapper; +import com.sunyard.chsm.mapper.IpWhitelisttMapper; import com.sunyard.chsm.model.entity.AppService; import com.sunyard.chsm.model.entity.Application; +import com.sunyard.chsm.model.entity.IpWhitelist; import com.sunyard.chsm.param.AppTokenReq; import com.sunyard.chsm.param.AppTokenResp; import com.sunyard.chsm.utils.CodecUtils; +import com.sunyard.chsm.utils.IpUtils; import com.sunyard.chsm.utils.gm.BCSM3Utils; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Header; @@ -19,8 +23,10 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; import java.util.*; import java.util.stream.Collectors; @@ -41,6 +47,10 @@ public class AppLoginService { private ApplicationMapper applicationMapper; @Resource private AppServiceMapper appServiceMapper; + @Resource + private HttpServletRequest request; + @Resource + private IpWhitelisttMapper ipWhitelisttMapper; public AppTokenResp getAppToken(AppTokenReq req) { Long random = req.getTimestamp(); @@ -49,6 +59,19 @@ public class AppLoginService { String appKey = req.getAppKey(); Application application = applicationMapper.selectByAppKey(appKey); Assert.isTrue(EnableStatus.ENABLED.getCode().equals(application.getStatus()), "此应用已停用"); + List list = ipWhitelisttMapper.selectList( + new LambdaQueryWrapper().eq(IpWhitelist::getAppId, application.getId()) + ); + if (!CollectionUtils.isEmpty(list)) { + String ip = IpUtils.getIpAddress(request); + IpWhitelist whitelist = list.stream() + .filter(it -> EnableStatus.ENABLED.getCode().equals(it.getStatus())) + .filter(it -> Objects.equals(ip, it.getIp())) + .findFirst() + .orElse(null); + Assert.notNull(whitelist, "IP:" + ip + "禁止访问!"); + } + String data = appKey + random + application.getAppSecret(); byte[] hmac = BCSM3Utils.hmac(application.getAppSecret().getBytes(), data.getBytes()); String serverHmac = CodecUtils.encodeBase64(hmac); diff --git a/chsm-web-server/src/test/java/api/BaseTest.java b/chsm-web-server/src/test/java/api/BaseTest.java index 9acef46..e119379 100644 --- a/chsm-web-server/src/test/java/api/BaseTest.java +++ b/chsm-web-server/src/test/java/api/BaseTest.java @@ -30,7 +30,7 @@ public abstract class BaseTest { protected static final String asymKeyTemplate = "asym-sm2-001"; protected static final String ak = "216205d408130d83d13c5072305b8b65"; protected static final String sk = "ae64515d1d5adec2cc6ae8726d0c1bbc"; - protected static final String server = "http://172.16.18.46:8900"; + protected static final String server = "http://172.16.18.46:9890"; protected static final RestTemplate restTemplate; protected static final String token; @@ -49,7 +49,12 @@ public abstract class BaseTest { R r = JsonUtils.objectMapper() .readValue(response.getBody(), new TypeReference>() { }); + if (!r.isSuccess()) { + log.warn(r.getMessage()); + throw new IllegalArgumentException(r.getMessage()); + } token = r.getResult().getToken(); + log.info("get token: {}", token); restTemplate = new RestTemplateBuilder() .rootUri(server) .defaultHeader("Authorization", "Bearer " + token)