Commit 5db3bca0 authored by 向怀芳's avatar 向怀芳 🎱

1. IP白名单03

parent 48c7badf
...@@ -12,6 +12,7 @@ import lombok.Getter; ...@@ -12,6 +12,7 @@ import lombok.Getter;
@AllArgsConstructor @AllArgsConstructor
public enum BizCodeConstant { public enum BizCodeConstant {
/* */ /* */
USER_PWD_LIMIT(99,""),
TEMP(0,""); TEMP(0,"");
private Integer code; private Integer code;
......
...@@ -193,6 +193,37 @@ public class WebUtils extends org.springframework.web.util.WebUtils { ...@@ -193,6 +193,37 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
return StringUtils.isBlank(ip) ? null : ip.split(",")[0]; return StringUtils.isBlank(ip) ? null : ip.split(",")[0];
} }
public String getIP(ServerHttpRequest request) {
HttpHeaders headers = request.getHeaders();
String ip = headers.getFirst("x-forwarded-for");
if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
// 多次反向代理后会有多个ip值,第一个ip才是真实ip
if (ip.indexOf(",") != -1) {
ip = ip.split(",")[0];
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = headers.getFirst("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = headers.getFirst("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = headers.getFirst("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = headers.getFirst("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = headers.getFirst("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddress().getAddress().getHostAddress();
}
return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
}
/** /**
* 从request 获取CLIENT_ID * 从request 获取CLIENT_ID
* *
......
package cn.sh.stc.sict.cloud.common.gateway.config;
import lombok.Data;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* @Description 网关不校验终端配置
* @Author
* @Date
*/
@Data
@Configuration
@RefreshScope
@ConditionalOnExpression("!'${whiteip}'.isEmpty()")
@ConfigurationProperties(prefix = "whiteip")
public class WhitIPConfig {
private List<String> whites = new ArrayList<>();
}
package cn.sh.stc.sict.cloud.common.gateway.filter; package cn.sh.stc.sict.cloud.common.gateway.filter;
import cn.sh.stc.sict.cloud.common.core.constant.Constant;
import cn.sh.stc.sict.cloud.common.core.constant.SecurityConstants; import cn.sh.stc.sict.cloud.common.core.constant.SecurityConstants;
import cn.sh.stc.sict.cloud.common.core.util.R;
import cn.sh.stc.sict.cloud.common.core.util.WebUtils;
import cn.sh.stc.sict.cloud.common.gateway.config.WhitIPConfig;
import cn.sh.stc.sict.cloud.common.gateway.util.IPStrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
...@@ -18,8 +28,7 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G ...@@ -18,8 +28,7 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
/** /**
* @Description * @Description <p>
* <p>
* 全局拦截器,作用所有的微服务 * 全局拦截器,作用所有的微服务
* <p> * <p>
* 1. 对请求头中参数进行处理 from 参数进行清洗 * 1. 对请求头中参数进行处理 from 参数进行清洗
...@@ -31,8 +40,11 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.a ...@@ -31,8 +40,11 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.a
*/ */
@Slf4j @Slf4j
@Component @Component
@AllArgsConstructor
public class RequestGlobalFilter implements GlobalFilter, Ordered { public class RequestGlobalFilter implements GlobalFilter, Ordered {
private static final String HEADER_NAME = "X-Forwarded-Prefix"; private static final String HEADER_NAME = "X-Forwarded-Prefix";
private final WhitIPConfig whitIPConfig;
private final ObjectMapper objectMapper;
/** /**
* Process the Web request and (optionally) delegate to the next * Process the Web request and (optionally) delegate to the next
...@@ -46,12 +58,38 @@ public class RequestGlobalFilter implements GlobalFilter, Ordered { ...@@ -46,12 +58,38 @@ public class RequestGlobalFilter implements GlobalFilter, Ordered {
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 清洗请求头中from 参数 // 1. 清洗请求头中from 参数
ServerHttpRequest request = exchange.getRequest().mutate() ServerHttpRequest request = exchange.getRequest().mutate()
.headers(httpHeaders -> {httpHeaders.remove(SecurityConstants.FROM);}) .headers(httpHeaders -> {
httpHeaders.remove(SecurityConstants.FROM);
})
.build(); .build();
// IP白名单 // IP白名单
String ip = WebUtils.getIP(request);
log.error("RemoteAddress ===================> {}", request.getRemoteAddress()); log.error("RemoteAddress ===================> {}", request.getRemoteAddress());
try {
if (!IPStrUtil.matches(ip, whitIPConfig.getWhites())) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED);
response.getHeaders().set("Content-type", "application/json; charset=utf-8");
return response.writeWith(Mono.just(response.bufferFactory()
.wrap(objectMapper.writeValueAsBytes(
R.builder().msg("没有权限访问")
.code(Constant.BYTE_NO).build()))));
}
} catch (
Exception e) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED);
response.getHeaders().set("Content-type", "application/json; charset=utf-8");
try {
return response.writeWith(Mono.just(response.bufferFactory()
.wrap(objectMapper.writeValueAsBytes(
R.builder().msg(e.getMessage())
.code(Constant.BYTE_NO).build()))));
} catch (JsonProcessingException e1) {
log.error("对象输出异常", e1);
}
}
// 2. 重写StripPrefix // 2. 重写StripPrefix
addOriginalRequestUrl(exchange, request.getURI()); addOriginalRequestUrl(exchange, request.getURI());
String rawPath = request.getURI().getRawPath(); String rawPath = request.getURI().getRawPath();
......
package cn.sh.stc.sict.cloud.common.gateway.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import java.util.List;
public class IPStrUtil {
static char START = '*';
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, List<String> strs) {
if (StrUtil.isEmpty(str) || CollUtil.isEmpty(strs)) {
return false;
}
for (String testStr : strs) {
if (matches(str, testStr)) {
return true;
}
}
return false;
}
/**
* 查找指定字符串是否匹配指定字符串数组中的任意一个字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, String... strs) {
if (StrUtil.isEmpty(str) || StrUtil.isAllEmpty(str)) {
return false;
}
for (String testStr : strs) {
if (matches(str, testStr)) {
return true;
}
}
return false;
}
/**
* 查找指定字符串是否匹配
*
* @param str 指定字符串
* @param pattern 需要检查的字符串
* @return 是否匹配
*/
public static boolean matches(String str, String pattern) {
if (StrUtil.isEmpty(pattern) || StrUtil.isEmpty(str)) {
return false;
}
pattern = pattern.replaceAll("\\s*", ""); // 替换空格
int beginOffset = 0; // pattern截取开始位置
int formerStarOffset = -1; // 前星号的偏移位置
int latterStarOffset = -1; // 后星号的偏移位置
String remainingURI = str;
String prefixPattern = "";
String suffixPattern = "";
boolean result = false;
do {
formerStarOffset = StrUtil.indexOf(pattern, START, beginOffset);
prefixPattern = StrUtil.sub(pattern, beginOffset, formerStarOffset > -1 ? formerStarOffset : pattern.length());
// 匹配前缀Pattern
result = remainingURI.contains(prefixPattern);
// 已经没有星号,直接返回
if (formerStarOffset == -1) {
return result;
}
// 匹配失败,直接返回
if (!result)
return false;
if (!StrUtil.isEmpty(prefixPattern)) {
remainingURI = StrUtil.subAfter(str, prefixPattern, true);
}
// 匹配后缀Pattern
latterStarOffset = StrUtil.indexOf(pattern, START, formerStarOffset + 1);
suffixPattern = StrUtil.sub(pattern, formerStarOffset + 1, latterStarOffset > -1 ? latterStarOffset : pattern.length());
result = remainingURI.contains(suffixPattern);
// 匹配失败,直接返回
if (!result)
return false;
if (!StrUtil.isEmpty(suffixPattern)) {
remainingURI = StrUtil.subAfter(str, suffixPattern, true);
}
// 移动指针
beginOffset = latterStarOffset + 1;
}
while (!StrUtil.isEmpty(suffixPattern) && !StrUtil.isEmpty(remainingURI));
return true;
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj) {
return (T) obj;
}
}
...@@ -142,6 +142,8 @@ public class SysUserBase extends Model<SysUserBase> { ...@@ -142,6 +142,8 @@ public class SysUserBase extends Model<SysUserBase> {
@ApiModelProperty(hidden = true, value = "") @ApiModelProperty(hidden = true, value = "")
private Date updateTime; private Date updateTime;
private Date lastPwdTime;
/** /**
* 主键值 * 主键值
*/ */
......
...@@ -2,6 +2,7 @@ package cn.sh.stc.sict.cloud.upms.controller.web; ...@@ -2,6 +2,7 @@ package cn.sh.stc.sict.cloud.upms.controller.web;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.sh.stc.sict.cloud.common.core.constant.Constant; import cn.sh.stc.sict.cloud.common.core.constant.Constant;
import cn.sh.stc.sict.cloud.common.core.constant.enums.BizCodeConstant;
import cn.sh.stc.sict.cloud.common.core.util.NumberUtil; import cn.sh.stc.sict.cloud.common.core.util.NumberUtil;
import cn.sh.stc.sict.cloud.common.log.annotation.SysLog; import cn.sh.stc.sict.cloud.common.log.annotation.SysLog;
import cn.sh.stc.sict.cloud.common.security.util.SecurityUtils; import cn.sh.stc.sict.cloud.common.security.util.SecurityUtils;
...@@ -118,7 +119,7 @@ public class SysUserBaseController { ...@@ -118,7 +119,7 @@ public class SysUserBaseController {
dto.setRoleList(roleList); dto.setRoleList(roleList);
dto.setMenuList(menuList); dto.setMenuList(menuList);
return new R(dto); return new R(dto).setBizCode(BizCodeConstant.USER_PWD_LIMIT.getCode());
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment