过滤器
1.FoundFilter(UserCredentialFilter) 用户凭证管控过滤器
@Slf4j @Component public class FoundFilter extends AbstractGatewayFilterFactory<FilterConfig> implements Ordered{ public FoundFilter(){super(FilterConfig.class)} public GatewayFilter apply(FilterConfig config){ return (exchange,chain)->{ //如何关闭用户凭证,则放行 if (!bizConfig.getSecurity().isUserCredentials()){ return chain.filter(exchange); } ServerHttpRequest request = exchange.getRequest(); String token = request.getHeaders().getFirst("Authorization"); String thirdFlag = request.getHeaders().getFirst("isThird"); Map<String,String> param = httpKit.toRemoteHeaderMap(token, thirdFlag); //从云网API调用 List<RemoteCookieCtrl> cookieConfigs = null; try{ cookieConfigs = remoteUserCredentialsService.getCredentials(param); }catch(Exception e){ log.error("远程获取用户凭证管控请求错误:{}",e.getMessage()); return chain.filter(exchange); } //列表为空,不校验放行 if(CollectionUtil.isEmpty(cookieConfigs)){ return chain.filter(exchange); } Map<String,HttpCookie> cookies = request.getCookies().toSingleValueMap(); for (Map.Entry<String,HttpCookie> cookie: cookies.entrySet()){ for( RemoteCookieCtrl cookieConfig: cookieConfigs) { if (cookie.getValue().getName().equals(cookieConfig.getCookieName()) && cookie.getValue().getValue().contains(cookieConfig.getCookieValue())){ // 存在匹配的,就放行 return chain.filter(exchange); } } } SysUser user = null; saveLog(request,user); Response response = new Response(302,"未包含指定标识",null); return httpKit.response(exchange,response); }; }
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void saveLog(ServerHttpRequest request,SysUser user){
String currentTime = sdf.format(now());
String username = "-";
if(!StringUtils.isEmpty(user.getUserName())){
username =user.getUserName();
}
String realIp = httpKit.findXRealIp(request);
RemoteSysLog sysLog = new RemoteSysLog();
sysLog.setCreateTime(currentTime);
sysLog.setRemoteAddr(realIp);
sysLog.setRequestUri(request.getURI().getPath());
sysLog.setMethod(request.getMethod().name());
//异步执行
executeService.submit(()->{
logService.save(sysLog);
}));
}
}
2. HttpUtil http工具类
@Component public class HttpUtil { public Map<String,String> toRemoteHeaderMap(String token,String thirdFlag){ Map<String,String> param = new HashMap(); if (!StringUtils.isEmpty(token)){ param .put("Authorization",token); } if (!StringUtils.isEmpty(thirdFlag)){ param.put("isThird",thirdFlag); } return param; } public string execute(String url,Map<String,String> headerMap,String method,String body) throws Exception{ CloseableHttpClient httpClient = HttpClients.createDefault(); RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(3000) .setSocketTimeout(30000); .build(); HttpRequestBase httpRequest; if ("GET".equalsIgnoreCase(method)){ httpRequest = new HttpGet(url); }else if ("POST".equalsIgnoreCase(method)){ httpRequest = new HttpPost(url); if (!StringUtils.isEmpty(body) ){ StringEntity entity = new StringEntity(body, "UTF-8"); entity.setContentEncoding("UTF-8"); entity.setContentType("application/json"); ((HttpPost)httpRequest).setEntity(entity); } } else { throw new IllegalArgumentException("Unsupported HTTP method:"+ method); } httpRequest.setConfig(requestConfig); if (!CollectionUtils.isEmpty(headerMap)){ for (Map.Entry<String,String> entry: headerMap.entrySet()){ httpRequest.setHeader(entry.getKey(),entry.getValue()); } } CloseableHttpResponse response = httpClient.execute(httpRequest); try{ int responseCode = response.getstatusLine().getStatusCode(); if (responseCode = 200){ return EntityUtils.toString(response.getEntity()); } else{ throw new IOException("Http request failed!,response="+EntityUtils.toString(response.getEntity())) } }finally{ response.close(); } } //获得请求响应的body public String getBody(String url,Map<String,String> headerMap) throws Exception { return execute(url,headerMap,"GET",null); } public String postBody(String url,Map<String,String> headerMap.String body) throws Exception { return execute(url,headerMap,"POST",body); } //响应
public Mono<Void> response(ServerWebExchange exchange,Response r){
ServerHttpResponse response = exchange.getResponse();
//客户端无法获取接口支持的请求方法
response.getHeaders().remove("Allow");
//浏览器会拦截跨域请求,触发跨域报错
response.getHeaders().remove("Access-Control-Allow-Origin");
response.setStatusCode(HttpStatus.valueOf(r.getCode()));
return response.writeWith(Mono.just(response.bufferFactory.wrap(("{\"code\":"+r.getCode()+",\"message\":\""+r.getMessage()+"\"}").getBytes())));
}
private String[] IP_HEADER_CANDIDATES = {
"X-Forwarded-For",
"Proxy-Client-IP",
"WL-Proxy-Client-IP",
"HTTP_X_FORWARDED_FOR",
"HTTP_X_FORWARDED",
"HTTP_X_CLUSTER_CLIENT_IP",
"HTTP_CLIENT_IP",
"HTTP_FORWARDED_FOR",
"HTTP_FORWARDED",
"HTTP_VIA",
"X-Real-IP"
};
//获取客户端真实ip
public String findXRealIp(ServerHttpRequest request){
//优先从常见的代理头中查找
for(String header: IP_HEADER_CANDIDATES){
List<String> headerValues = request.getHeaders().get(header);
if (!CollectionUtils.isEmpty(headerValues)){
String ip = headerValues.get(0);
if (!StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip) && ip.contains(",")){
//处理x-forward-ip多值情况
ip = ip.split(",")[0].trim();
}
retunn ip;
}
}
//如果所有头都没有,则从远程地址获取
InetSocketAddress remoteAddress = request.getRemoteAddress();
if (remoteAddress != null)
{
return remoteAddress.getAddress().getHostAddress();
}
//如果都获取不到,返回一个默认值
return "unknown";
}
}
3.CacheBodyFilter 请求体缓存过滤器
@Slf4j
@Component
public class CacheBodyFilter extends AbstactGatewayFilterFactory<FilterConfig> implements Ordered {
public CacheBodyFilter(){
super(FilterConfig.class);
}
String contentType = "application/json,application/x-www-form-urlencoded";
List<String> allowedContentType = Arrays.asList(contentType.split(","));
public GatewayFilter apply(FilterConfig config){
return (exchange,chain) -> {
if (!bizConfig.getSecurity().isTamperMode()){
return chain.filter(exchange);
}
ServerHttpRequest request = exchange.getRequest();
String contentType = request.getHeaders().getFirst("Content-Type");
if (contentType != null && allowedContentType.contains(contentType)){
return DataBufferUtils.join(exchange.getRequest().getBody())
.flatMap(dataBuffer->{
if (dataBuffer.readableByteCount()>config.getMaxBodySize()){
exchange.getResponse().setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE);
DataBufferUtils.release(dataBuffer);
return exchange.getResponse().setComplete();
}
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
String body = new String(bytes,StandardCharsets.UTF_8);
//将body缓存到exchange属性中,供后续使用
exchange.getAttributes().put("cachedRequestBody",body);
return chain.filter(buildNewExchange(exchange,body));
});
}
//处理multipart/form-data请求
if (contentType!= null && contentType.contains("multipart/form-data")){
return exchange.getMultipartData()
.flatMap(multipartData->{
if (multipartData == null || multipartData.isEmpty()){
return chain.filter(exchange);
}
// 创建最终的结果map
Map<String,Object> resultMap = new HashMap<>();
//处理文件部分
List<Map<String,Object>> fileList = new ArrayList<>();
return Flux.fromIterable(multipartData.entrySet())
.flatMap(entry -> {
String key = entry.getKey();
List<Part> parts = entry.getValue();
return Flux.fromIterable(parts)
.flatMap(part -> {
if(part instanceof FilePart){
//处理文件
FilePart filePart = (FilePart)part;
Map<String,Object> fileInfo = new HashMap<>();
fileInfo.put("fileName",filePart.fileName());
fileInfo.put("contentType",filePart.headers().getContentType()!=null ? filePart.headers().getContentType().toString():"application/octet-stream");
//处理文件内容计算sha56
return filePart.content().reduce(new ByteArrayOutputStream(),(outputStream,dataBuffer) ->{
try{
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
outputStream.write(bytes);
DataBufferUtils.release(dataBuffer);
}catch(IOException e){
throw new RuntimeException(e);
}
return outputStream;
})
.map(outputStream -> {
try{
String sha256 = DigestUtil.sha256Hex(outputStream.toByteArray());
fileInfo.put("file",sha256);
}catch(Exception e){
throw new RuntimeException(e);
}
fileList.add(fileInfo);
return fileInfo;
});
}else if (part instanceof FormFieldPart){
//处理表单字段
FormFieldPart formField = (FormFieldPart)part;
resultMap.put(key,formField.value());
return Mono.just(formField);
}else {
return Mono.just(part);
}
});
}).collectList()
.doOnNext(ignored -> {
//将文件列表放入结果map
if (!fileList.isEmpty()){
resultMap.put("file",fileList);
}
}).then(Mono.fromRunnable(()->{
//将完整的结果缓存到exchange属性中
if (!resultMap.isEmpty()){
exchange.getAttributes().put("cachedMultipartFiles",resultMap);
}
}))
.then(chain.filter(exchange));
});
}
return chain.filter(exchange);
};
}
//构建新的请求体
public ServerWebExchange buildNewExchange(ServerWebExchange exchange,String body){
//3 重新构建请求体
bytes[] newBytes = body.getBytes(StandardCharsets.UTF_8);
DataBuffer newDataBuffer = exchange.getResponse().bufferFactory().wrap(newBytes);
// 使用ServerHttpRequestDecorator 包装请求
ServerHttpRequest decoratedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
public Flux<DataBuffer> getBody{ return Flux.just(newDataBuffer);}
};
//4.创建新的ServerWebExchange
return exchange.mutate()
.request(decoratedRequest)
.build();
}
}
4. CsrfFilter CSRF过滤器
@Slf4j

浙公网安备 33010602011771号