白名单
This commit is contained in:
parent
7d2d5c9e3c
commit
8be178317a
@ -4,13 +4,13 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.sunyard.chsm.config.IpFilter;
|
|
||||||
import com.sunyard.chsm.dto.IpWhitelistDTO;
|
import com.sunyard.chsm.dto.IpWhitelistDTO;
|
||||||
import com.sunyard.chsm.enums.EnableStatus;
|
import com.sunyard.chsm.enums.EnableStatus;
|
||||||
import com.sunyard.chsm.mapper.IpWhitelisttMapper;
|
import com.sunyard.chsm.mapper.IpWhitelisttMapper;
|
||||||
import com.sunyard.chsm.model.entity.IpWhitelist;
|
import com.sunyard.chsm.model.entity.IpWhitelist;
|
||||||
import com.sunyard.chsm.service.IpWhitelistService;
|
import com.sunyard.chsm.service.IpWhitelistService;
|
||||||
import com.sunyard.chsm.utils.IpUtils;
|
import com.sunyard.chsm.utils.IpUtils;
|
||||||
|
import com.sunyard.config.IpFilter;
|
||||||
import com.sunyard.ssp.utils.SecurityUtil;
|
import com.sunyard.ssp.utils.SecurityUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.sunyard.chsm.config;
|
package com.sunyard.config;
|
||||||
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
@ -53,7 +53,7 @@ public class IpFilter extends OncePerRequestFilter implements ApplicationRunner
|
|||||||
syncWhiteIps();
|
syncWhiteIps();
|
||||||
}
|
}
|
||||||
String ip = IpUtils.getIpAddress(request);
|
String ip = IpUtils.getIpAddress(request);
|
||||||
if (!enableWhiteIp || CollectionUtils.isEmpty(whiteIps) || whiteIps.contains(ip)) {
|
if (!enableWhiteIp || whiteIps.contains(ip)) {
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
@ -2,10 +2,10 @@ package com.sunyard.ssp.modules.sysconf.paramconf.serviceimpl;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.sunyard.chsm.config.IpFilter;
|
|
||||||
import com.sunyard.chsm.mapper.ParamConfMapper;
|
import com.sunyard.chsm.mapper.ParamConfMapper;
|
||||||
import com.sunyard.chsm.model.entity.ParamConf;
|
import com.sunyard.chsm.model.entity.ParamConf;
|
||||||
import com.sunyard.chsm.service.IpWhitelistService;
|
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.sysconf.paramconf.service.IParamConfService;
|
||||||
import com.sunyard.ssp.modules.user.entity.ScPermission;
|
import com.sunyard.ssp.modules.user.entity.ScPermission;
|
||||||
import com.sunyard.ssp.modules.user.service.IScPermissionService;
|
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 org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static com.sunyard.chsm.constant.ParamConfKeyConstant.APPROVAL_TRUE;
|
import static com.sunyard.chsm.constant.ParamConfKeyConstant.*;
|
||||||
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.ssp.common.constant.CommonConstant.STATUS_DISABLE;
|
import static com.sunyard.ssp.common.constant.CommonConstant.STATUS_DISABLE;
|
||||||
import static com.sunyard.ssp.common.constant.CommonConstant.STATUS_NORMAL;
|
import static com.sunyard.ssp.common.constant.CommonConstant.STATUS_NORMAL;
|
||||||
|
|
||||||
|
@ -1,15 +1,22 @@
|
|||||||
package com.sunyard.chsm.auth;
|
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.R;
|
||||||
|
import com.sunyard.chsm.model.entity.IpWhitelist;
|
||||||
import com.sunyard.chsm.service.AppLoginService;
|
import com.sunyard.chsm.service.AppLoginService;
|
||||||
|
import com.sunyard.chsm.utils.IpUtils;
|
||||||
import com.sunyard.chsm.utils.JsonUtils;
|
import com.sunyard.chsm.utils.JsonUtils;
|
||||||
import io.jsonwebtoken.ExpiredJwtException;
|
import io.jsonwebtoken.ExpiredJwtException;
|
||||||
import io.jsonwebtoken.JwtException;
|
import io.jsonwebtoken.JwtException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
@ -18,9 +25,11 @@ import javax.servlet.ServletException;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.Enumeration;
|
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;
|
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
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AppTokenFilter extends OncePerRequestFilter {
|
public class AppTokenFilter extends OncePerRequestFilter implements InitializingBean {
|
||||||
|
|
||||||
|
public static Map<Long, List<String>> WHITE_IP_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public static final Collection<String> WHITE_URL = Arrays.asList(
|
public static final Collection<String> WHITE_URL = Arrays.asList(
|
||||||
"/appUser/getAppToken",
|
"/appUser/getAppToken",
|
||||||
@ -40,6 +51,7 @@ public class AppTokenFilter extends OncePerRequestFilter {
|
|||||||
);
|
);
|
||||||
|
|
||||||
private final AppLoginService appLoginService;
|
private final AppLoginService appLoginService;
|
||||||
|
private final IpWhitelisttMapper ipWhitelisttMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||||
@ -58,6 +70,16 @@ public class AppTokenFilter extends OncePerRequestFilter {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
AppUser user = appLoginService.verifyToken(tokenValue);
|
AppUser user = appLoginService.verifyToken(tokenValue);
|
||||||
|
List<String> 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);
|
request.setAttribute(ATTRIBUTE_APP_USER, user);
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
} catch (ExpiredJwtException ex) {
|
} catch (ExpiredJwtException ex) {
|
||||||
@ -110,4 +132,21 @@ public class AppTokenFilter extends OncePerRequestFilter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws ServletException {
|
||||||
|
super.afterPropertiesSet();
|
||||||
|
|
||||||
|
Executors.newSingleThreadScheduledExecutor()
|
||||||
|
.scheduleWithFixedDelay(() -> {
|
||||||
|
|
||||||
|
List<IpWhitelist> list = ipWhitelisttMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<IpWhitelist>()
|
||||||
|
.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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,12 @@ public class DeviceManager implements InitializingBean {
|
|||||||
if (atomicInteger.get() > Integer.MAX_VALUE - 10000) {
|
if (atomicInteger.get() > Integer.MAX_VALUE - 10000) {
|
||||||
atomicInteger.set(1);
|
atomicInteger.set(1);
|
||||||
}
|
}
|
||||||
|
if (CollectionUtils.isEmpty(serviceDeviceMap)) {
|
||||||
|
log.warn("系统内没有可以设备..service Device is empty");
|
||||||
|
TMKContext soft = getSoftContext();
|
||||||
|
Assert.notNull(soft, "应用: " + user.getName() + "没有可用的密码设备");
|
||||||
|
return soft;
|
||||||
|
}
|
||||||
List<DeviceContext> contexts = serviceDeviceMap.entrySet().stream()
|
List<DeviceContext> contexts = serviceDeviceMap.entrySet().stream()
|
||||||
.filter(it -> serviceIds.contains(it.getKey()))
|
.filter(it -> serviceIds.contains(it.getKey()))
|
||||||
.map(Map.Entry::getValue)
|
.map(Map.Entry::getValue)
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
package com.sunyard.chsm.service;
|
package com.sunyard.chsm.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.sunyard.chsm.auth.AppUser;
|
import com.sunyard.chsm.auth.AppUser;
|
||||||
import com.sunyard.chsm.constant.SecurityConstant;
|
import com.sunyard.chsm.constant.SecurityConstant;
|
||||||
import com.sunyard.chsm.enums.EnableStatus;
|
import com.sunyard.chsm.enums.EnableStatus;
|
||||||
import com.sunyard.chsm.mapper.AppServiceMapper;
|
import com.sunyard.chsm.mapper.AppServiceMapper;
|
||||||
import com.sunyard.chsm.mapper.ApplicationMapper;
|
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.AppService;
|
||||||
import com.sunyard.chsm.model.entity.Application;
|
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.AppTokenReq;
|
||||||
import com.sunyard.chsm.param.AppTokenResp;
|
import com.sunyard.chsm.param.AppTokenResp;
|
||||||
import com.sunyard.chsm.utils.CodecUtils;
|
import com.sunyard.chsm.utils.CodecUtils;
|
||||||
|
import com.sunyard.chsm.utils.IpUtils;
|
||||||
import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Header;
|
import io.jsonwebtoken.Header;
|
||||||
@ -19,8 +23,10 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -41,6 +47,10 @@ public class AppLoginService {
|
|||||||
private ApplicationMapper applicationMapper;
|
private ApplicationMapper applicationMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private AppServiceMapper appServiceMapper;
|
private AppServiceMapper appServiceMapper;
|
||||||
|
@Resource
|
||||||
|
private HttpServletRequest request;
|
||||||
|
@Resource
|
||||||
|
private IpWhitelisttMapper ipWhitelisttMapper;
|
||||||
|
|
||||||
public AppTokenResp getAppToken(AppTokenReq req) {
|
public AppTokenResp getAppToken(AppTokenReq req) {
|
||||||
Long random = req.getTimestamp();
|
Long random = req.getTimestamp();
|
||||||
@ -49,6 +59,19 @@ public class AppLoginService {
|
|||||||
String appKey = req.getAppKey();
|
String appKey = req.getAppKey();
|
||||||
Application application = applicationMapper.selectByAppKey(appKey);
|
Application application = applicationMapper.selectByAppKey(appKey);
|
||||||
Assert.isTrue(EnableStatus.ENABLED.getCode().equals(application.getStatus()), "此应用已停用");
|
Assert.isTrue(EnableStatus.ENABLED.getCode().equals(application.getStatus()), "此应用已停用");
|
||||||
|
List<IpWhitelist> list = ipWhitelisttMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<IpWhitelist>().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();
|
String data = appKey + random + application.getAppSecret();
|
||||||
byte[] hmac = BCSM3Utils.hmac(application.getAppSecret().getBytes(), data.getBytes());
|
byte[] hmac = BCSM3Utils.hmac(application.getAppSecret().getBytes(), data.getBytes());
|
||||||
String serverHmac = CodecUtils.encodeBase64(hmac);
|
String serverHmac = CodecUtils.encodeBase64(hmac);
|
||||||
|
@ -30,7 +30,7 @@ public abstract class BaseTest {
|
|||||||
protected static final String asymKeyTemplate = "asym-sm2-001";
|
protected static final String asymKeyTemplate = "asym-sm2-001";
|
||||||
protected static final String ak = "216205d408130d83d13c5072305b8b65";
|
protected static final String ak = "216205d408130d83d13c5072305b8b65";
|
||||||
protected static final String sk = "ae64515d1d5adec2cc6ae8726d0c1bbc";
|
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 RestTemplate restTemplate;
|
||||||
protected static final String token;
|
protected static final String token;
|
||||||
|
|
||||||
@ -49,7 +49,12 @@ public abstract class BaseTest {
|
|||||||
R<AppTokenResp> r = JsonUtils.objectMapper()
|
R<AppTokenResp> r = JsonUtils.objectMapper()
|
||||||
.readValue(response.getBody(), new TypeReference<R<AppTokenResp>>() {
|
.readValue(response.getBody(), new TypeReference<R<AppTokenResp>>() {
|
||||||
});
|
});
|
||||||
|
if (!r.isSuccess()) {
|
||||||
|
log.warn(r.getMessage());
|
||||||
|
throw new IllegalArgumentException(r.getMessage());
|
||||||
|
}
|
||||||
token = r.getResult().getToken();
|
token = r.getResult().getToken();
|
||||||
|
log.info("get token: {}", token);
|
||||||
restTemplate = new RestTemplateBuilder()
|
restTemplate = new RestTemplateBuilder()
|
||||||
.rootUri(server)
|
.rootUri(server)
|
||||||
.defaultHeader("Authorization", "Bearer " + token)
|
.defaultHeader("Authorization", "Bearer " + token)
|
||||||
|
Loading…
Reference in New Issue
Block a user