1.Filter
package com.jinruaneducate.module.filter;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 参数校验过滤器:
* 1.获取请求参数
* 2.对获取到的请求参数进行处理(解密、字符串替、请求参数分类截取等等 )
* 3.把处理后的参数放回到请求列表里面
*/
@WebFilter(filterName = "decodeParameterFilter",
displayName = "decodeParameterFilter",
urlPatterns = {"/*"},
asyncSupported = true,
initParams = @WebInitParam(
name = "excludedPages",
value = "/webServer/upload," +
"/webServer/uplodFileExcle," +
"/webServer/downFileExcle," +
"/webServer/downFileImportInfo," +
"/webServer/view/," +
"/userAuth/," +
"/app/sysUsercourseLikeit/add," +
"/app/sysSourcePay/add," +
"/app/sysUsercourseComment/add," +
"/app/addUserHobby," +
"/sysUserAttention/addApp," +
"/sysForumsQuestion/addApp," +
"/sysForumsQuestionResult/addApp," +
"/sysForumsPost/addApp," +
"/resource/downLoadSysResource," +
"/userAuth/exportUser," +
"/SysAppVersion/fileUpload," +
"/alipay/notify_url," +
"/sysDept/getDeptList," +
"/sysSensitiveWord/importSensitiveWord," +
"/userAuth/importUser," +
"/adminHome/dashboard")
)
public class DecodeParameterFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(DecodeParameterFilter.class);
/**
* 不需要过滤的地址
*/
private String excludedPage = "";
private String[] excludedPages;
private Base64 base64 = new Base64();
/**
* 是否需要过滤 false 不需要过滤,true需要过滤
*
* @param requestUrl 请求的url
* @return
*/
private boolean isPast(String requestUrl) {
for (String url : excludedPages) {
Pattern pattern = Pattern.compile(url);
Matcher matcher = pattern.matcher(requestUrl);
boolean rs = matcher.find();
if (rs) {
return false;
}
}
return true;
}
@Override
public void destroy() {
log.info("过滤器执行结束");
}
@SuppressWarnings("unchecked")
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
/*String uri = ((HttpServletRequest) request).getRequestURI();
String token = ((HttpServletRequest) request).getHeader("Authorization");
log.info("token =" + token);
if (isPast(uri)) {
Base64 base64 = new Base64();
String method = ((HttpServletRequest) request).getMethod();
String url = ((RequestFacade) request).getServletPath();
if ("POST".equals(method) || "GET".equals(method)) {
MyHttpServletRequestWrapper requestWrapper = new MyHttpServletRequestWrapper((HttpServletRequest) request);
BufferedReader br = requestWrapper.getReader();
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line);
}
String content = requestWrapper.getHeader("content-type");
if ("POST".equals(method) &&
("application/x-www-form-urlencoded".equals(content) ||
"application/x-www-form-urlencoded; charset=utf-8".equals(content))) {
String[] param = sb.toString().split("&");
Map map = new HashMap();
for (String a : param) {
if (a.split("=").length == 1) {
map.put(a.split("=")[0], "");
} else if (a.split("=").length == 2) {
map.put(a.split("=")[0], a.split("=")[1]);
}
}
requestWrapper.setParameters(map);
}
*//*JSONObject jsonObject = JSONObject.parseObject(sb.toString());
String json = "";*//*
// Map<String, Object> map = JSON.toJavaObject(jsonObject, Map.class);
*//*if (null != map) {
String sign = (String) map.get("sign");
String MdSign = (String) map.get("MdSign");
if (StringUtils.isNotEmpty(sign)) { // 外部系统调取是会传入sign(安全公钥)
String params = (String) map.get("sourceParameter");
if (StringUtils.isNotEmpty(MdSign) && validateSign(sign, params, request)) {
json = decodeParameter(params);
} else {
json = decodeParameter(params);
}
} else { // 浏览器需base64加密
//json = new String(base64.decode((String) map.get("sourceParameter")), "UTF-8");
json = new String(base64.decode((String) map.get("sourceParameter")));
}
}*//*
*//*requestWrapper.setBody(json.getBytes("UTF-8"));
if ("{}".equals(json) || "".equals(json)) {
// 1.获取需要处理的参数
String sourceParameter = requestWrapper.getParameter("sourceParameter");
if (!StringUtils.isBlank(sourceParameter)) {
String decodeParameter = new String(base64.decode(sourceParameter), "UTF-8");
jsonObject = JSONObject.parseObject(decodeParameter);
map = JSON.toJavaObject(jsonObject, Map.class);
// 2.把处理后的参数放回去(这里是大小转小写处理)
requestWrapper.setParameters(map);
}
} else {
// 判断pc还是app
*//**//* jsonObject = JSONObject.parseObject(json);
map = JSON.toJavaObject(jsonObject, Map.class);
// requestWrapper.setParameters(map);
*//**//**//**//* String terminal = requestWrapper.getHeader("User-Agent");
map.put("cterminal", null != terminal && terminal.contains("Windows NT") ? "B" : "C");*//**//**//**//*
// 2.把处理后的参数放回去(这里是大小转小写处理)
requestWrapper.setParameters(map);*//**//*
}*//*
// 放行
//chain.doFilter(requestWrapper, response);
chain.doFilter(request, response);
// 此处记录一下请求接口的人员/用户
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}*/
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
excludedPage = filterConfig.getInitParameter("excludedPages");
if (excludedPage != null && excludedPage.length() > 0) {
excludedPages = excludedPage.split(",");
}
}
/**
* @param sign
* @param param
* @param request
* @return
*/
private boolean validateSign(String sign, String param, ServletRequest request) {
/* if (StringUtils.isBlank(sign)) {
throw new CommonJsonException( MsgEnum.E_400);
}
try {
String hash = MD5Util.MD5(param.getBytes("UTF-8"));
String oldSign = RsaUtils.decryptByPrivateKey( RsaUtils.privateKey_token, sign); // token密文,和页面浏览器的密文不是一个
if (!hash.equals(oldSign)) {
throw new CommonJsonException(MsgEnum.E_400);
}
request.setAttribute("sign", oldSign); // RSA加密后即便加密体不变但是每次都会改变的 但是md5不一样 加密多少次都一样
return true;
} catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
log.error("md5加密出错", e);
throw new CommonJsonException(MsgEnum.E_400);
} catch (IOException | InvalidKeyException | NoSuchPaddingException | BadPaddingException | InvalidKeySpecException | IllegalBlockSizeException e) {
log.error("rsa解密sign出错", e);
throw new CommonJsonException(MsgEnum.E_400);
}*/
return true;
}
/**
* @param sourceParameter
* @return
* @throws IOException
*/
private String decodeParameter(String sourceParameter) throws IOException {
String res;
try {
res = new String(base64.decode(sourceParameter), StandardCharsets.UTF_8);
} catch (Exception e) {
throw new IOException("HTTP参数解码异常", e);
}
return res;
}
}
2.HttpServletRequestWrapper
package com.jinruaneducate.module.untils;
import jodd.io.StreamUtil;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
/**
* 重写 HttpServletRequestWrapper
* 处理json报文请求
*/
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] body; //用于保存读取body中数据
private Map<String, String[]> params = new HashMap<String, String[]>(); // 用于存储请求参数
public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
//读取请求的数据保存到本类当中
body = StreamUtil.readBytes(request.getReader());
// 把请求参数添加到我们自己的map当中
this.params.putAll(request.getParameterMap());
}
//覆盖(重写)父类的方法
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
//覆盖(重写)父类的方法
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
@Override
public boolean isFinished() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isReady() {
// TODO Auto-generated method stub
return false;
}
@Override
public void setReadListener(ReadListener arg0) {
// TODO Auto-generated method stub
}
};
}
/**
* 获取body中的数据
*
* @return
*/
public byte[] getBody() {
return body;
}
/**
* 把处理后的参数放到body里面
*
* @param body
*/
public void setBody(byte[] body) {
this.body = body;
}
/**
* 添加参数到map中
*
* @param extraParams
*/
public void setParameters(Map<String, Object> extraParams) {
for (Map.Entry<String, Object> entry : extraParams.entrySet()) {
setParameter(entry.getKey(), entry.getValue());
}
}
/**
* 添加参数到map中
*
* @param name
* @param value
*/
public void setParameter(String name, Object value) {
try {
if (value != null) {
System.out.println("###############入参" + name + "###############出参" + value);
if (value instanceof String[]) {
params.put(name, (String[]) value);
} else if (value instanceof String) {
params.put(name, new String[]{URLDecoder.decode((String) value, "utf-8")});
} else {
params.put(name, new String[]{String.valueOf(value)});
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 重写getParameter,代表参数从当前类中的map获取
*
* @param name
* @return
*/
@Override
public String getParameter(String name) {
String[] values = params.get(name);
if (values == null || values.length == 0) {
return null;
}
return values[0];
}
/**
* 重写getParameterValues方法,从当前类的 map中取值
*
* @param name
* @return
*/
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
}
3.包装后效果