创建一个自定义的过滤器
代码语言:javascript复制import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@WebFilter(urlPatterns = "/*")
public class HttpReqFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// 头攻击检测 过滤主机名(非白名单中的直接返回 403)
String serverName = request.getServerName();
if (serverName != null && !checkBlankList(serverName)) {
System.out.println("[serverName deny access tips]->" serverName);
response.setStatus(403);
return;
}
// 转换成代理类(此处是为了获取返回参数)
ResponseWrapper wrapperResponse = new ResponseWrapper(response);
filterChain.doFilter(request, wrapperResponse);
// @todo 记录接口调用日志,超长参数和结果忽略
String resData = "";
// 返回值字节
byte[] content = wrapperResponse.getContent();
// 判断是否有值
if (content.length > 0) {
resData = new String(content, "UTF-8");
// 调用链
if (!isJson(resData)) {
// 如果不是json数据,可能是返回的数据流或下载文件,直接返回原数据
//把返回值输出到客户端
ServletOutputStream out = response.getOutputStream();
out.write(content);
out.flush();
} else {
// 处理返回数据
String cipherText = null;
try {
cipherText = resData;
//......根据需要处理返回值
} catch (Exception e) {
e.printStackTrace();
}
//把返回值输出到客户端
ServletOutputStream out = response.getOutputStream();
out.write(cipherText.getBytes());
out.flush();
}
}
if (resData.length() > 1024) {
resData = "...";
}
JSONObject reqParam = new JSONObject();
Map<String, String[]> parameterMap = request.getParameterMap();
for (Entry<String, String[]> entry : parameterMap.entrySet()) {
String key = entry.getKey();
String[] vals = entry.getValue();
if(vals.length>0) {
reqParam.put(key, vals[0]);
}else {
reqParam.put(key, "");
}
}
String params = reqParam.toJSONString();
if (params.length() > 1024) {
params = "...";
}
//输出日志
log.info(
"#{}#{}#{}#{}",
request.getRemoteAddr(),
request.getRequestURI(),
params,
resData
);
}
//判断主机是否存在白名单中
private boolean checkBlankList(String serverName){
if(serverName.equals("127.0.0.1"||serverName.equals("localhost")){//此处为自己网站的主机地址
return true;
}
return false;
}
/**
* 判断字符串数据是否为json
* @param content
* @return
*/
public static boolean isJson(String content) {
try {
JSON.parseObject(content);
return true;
} catch (Exception e) {
return false;
}
}
启动类添加注解
@ServletComponentScan
到此就配置完成了,是不是非常简单呢?
查看拦截host是否生效
这里就会看到我们拦截的 host 请求。
查看日志输出
具体输出什么内容,这里可以通过自己的业务需要来做不同的输出。我这里记录的是ip,请求参数,响应内容。