渗透测试漏洞修复
This commit is contained in:
parent
819512ea6c
commit
388012656c
|
|
@ -65,7 +65,7 @@ public class TokenService
|
||||||
redisService.deleteObject(oldTokenKey);
|
redisService.deleteObject(oldTokenKey);
|
||||||
}
|
}
|
||||||
// 存储新的token关联
|
// 存储新的token关联
|
||||||
redisService.setCacheObject(userTokenKey, token, expireTime, TimeUnit.SECONDS);
|
redisService.setCacheObject(userTokenKey, token, expireTime, TimeUnit.MINUTES);
|
||||||
String userKey = getTokenKey(loginUser.getToken());
|
String userKey = getTokenKey(loginUser.getToken());
|
||||||
// Jwt存储信息
|
// Jwt存储信息
|
||||||
Map<String, Object> claimsMap = new HashMap<String, Object>();
|
Map<String, Object> claimsMap = new HashMap<String, Object>();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.bonus.gateway.config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 马三炮
|
||||||
|
* @date 2025/11/26
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringEscapeUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSS过滤工具类
|
||||||
|
*/
|
||||||
|
public class XssFilterUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤特殊字符(黑名单方式)
|
||||||
|
*/
|
||||||
|
public static String filterSpecialChars(String input) {
|
||||||
|
if (input == null || input.isEmpty()) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
// 替换需过滤的字符(可根据需求调整替换策略:清空或转义)
|
||||||
|
return input.replaceAll("<", "<")
|
||||||
|
.replaceAll(">", ">")
|
||||||
|
.replaceAll("\"", """)
|
||||||
|
.replaceAll("'", "'")
|
||||||
|
.replaceAll("%", "%")
|
||||||
|
.replaceAll(";", ";")
|
||||||
|
.replaceAll("\\(", "(")
|
||||||
|
.replaceAll("\\)", ")")
|
||||||
|
.replaceAll("\\+", "+");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTML转义(推荐优先使用)
|
||||||
|
* 基于Apache Commons Text工具类,更全面的转义
|
||||||
|
*/
|
||||||
|
public static String htmlEscape(String input) {
|
||||||
|
return StringEscapeUtils.escapeHtml4(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组合过滤:先黑名单过滤,再HTML转义
|
||||||
|
*/
|
||||||
|
public static String xssFilter(String input) {
|
||||||
|
String filtered = filterSpecialChars(input);
|
||||||
|
return htmlEscape(filtered);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.bonus.gateway.config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 马三炮
|
||||||
|
* @date 2025/11/26
|
||||||
|
*/
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||||
|
|
||||||
|
public XssRequestWrapper(HttpServletRequest request) {
|
||||||
|
super(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getParameter(String name) {
|
||||||
|
String value = super.getParameter(name);
|
||||||
|
return XssFilterUtil.xssFilter(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getParameterValues(String name) {
|
||||||
|
String[] values = super.getParameterValues(name);
|
||||||
|
if (values == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
values[i] = XssFilterUtil.xssFilter(values[i]);
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String[]> getParameterMap() {
|
||||||
|
Map<String, String[]> map = super.getParameterMap();
|
||||||
|
map.forEach((key, values) -> {
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
values[i] = XssFilterUtil.xssFilter(values[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHeader(String name) {
|
||||||
|
String value = super.getHeader(name);
|
||||||
|
return XssFilterUtil.xssFilter(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,10 @@ package com.bonus.gateway.filter;
|
||||||
|
|
||||||
import com.bonus.common.core.utils.StringUtils;
|
import com.bonus.common.core.utils.StringUtils;
|
||||||
import com.bonus.common.core.utils.html.EscapeUtil;
|
import com.bonus.common.core.utils.html.EscapeUtil;
|
||||||
|
import com.bonus.gateway.config.XssFilterUtil;
|
||||||
import com.bonus.gateway.config.properties.XssProperties;
|
import com.bonus.gateway.config.properties.XssProperties;
|
||||||
import io.netty.buffer.ByteBufAllocator;
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||||
|
|
@ -20,6 +22,8 @@ import org.springframework.web.server.ServerWebExchange;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -27,6 +31,7 @@ import java.nio.charset.StandardCharsets;
|
||||||
*
|
*
|
||||||
* @author zys
|
* @author zys
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@ConditionalOnProperty(value = "security.xss.enabled", havingValue = "true")
|
@ConditionalOnProperty(value = "security.xss.enabled", havingValue = "true")
|
||||||
public class XssFilter implements GlobalFilter, Ordered
|
public class XssFilter implements GlobalFilter, Ordered
|
||||||
|
|
@ -46,10 +51,10 @@ public class XssFilter implements GlobalFilter, Ordered
|
||||||
return chain.filter(exchange);
|
return chain.filter(exchange);
|
||||||
}
|
}
|
||||||
// 非json类型,不过滤
|
// 非json类型,不过滤
|
||||||
if (!isJsonRequest(exchange))
|
/*if (!isJsonRequest(exchange))
|
||||||
{
|
{
|
||||||
return chain.filter(exchange);
|
return chain.filter(exchange);
|
||||||
}
|
}*/
|
||||||
// excludeUrls 不过滤
|
// excludeUrls 不过滤
|
||||||
String url = request.getURI().getPath();
|
String url = request.getURI().getPath();
|
||||||
if (StringUtils.matches(url, xss.getExcludeUrls()))
|
if (StringUtils.matches(url, xss.getExcludeUrls()))
|
||||||
|
|
@ -76,8 +81,14 @@ public class XssFilter implements GlobalFilter, Ordered
|
||||||
join.read(content);
|
join.read(content);
|
||||||
DataBufferUtils.release(join);
|
DataBufferUtils.release(join);
|
||||||
String bodyStr = new String(content, StandardCharsets.UTF_8);
|
String bodyStr = new String(content, StandardCharsets.UTF_8);
|
||||||
|
try {
|
||||||
|
bodyStr = java.net.URLDecoder.decode(bodyStr, StandardCharsets.UTF_8.name());
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
// 防xss攻击过滤
|
// 防xss攻击过滤
|
||||||
bodyStr = EscapeUtil.clean(bodyStr);
|
bodyStr = EscapeUtil.clean(bodyStr);
|
||||||
|
bodyStr = XssFilterUtil.filterSpecialChars(bodyStr);
|
||||||
// 转成字节
|
// 转成字节
|
||||||
byte[] bytes = bodyStr.getBytes();
|
byte[] bytes = bodyStr.getBytes();
|
||||||
NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
|
NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
|
||||||
|
|
@ -104,7 +115,7 @@ public class XssFilter implements GlobalFilter, Ordered
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否是Json请求
|
* 是否是Json请求
|
||||||
*
|
*
|
||||||
* @param exchange HTTP请求
|
* @param exchange HTTP请求
|
||||||
*/
|
*/
|
||||||
public boolean isJsonRequest(ServerWebExchange exchange)
|
public boolean isJsonRequest(ServerWebExchange exchange)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue