过滤器Filter技术(请求体二次解密处理技术):
对前端App请求进行过滤,在过滤中可以对前端请求体(body)进行二次处理,比如:前端请求的body为加密串、那么就可以在过滤器中对body加密串进行二次解密处理,再进行请求具体接口,处理逻辑如下:
过滤器 MyFilter.java
package com.sinosoft.config;import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory;import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Map;/*** 使用注解标注过滤器** @author 单红宇(365384722)* @WebFilter将一个实现了javax.servlet.Filter接口的类定义为过滤器 属性filterName声明过滤器的名称, 可选* 属性urlPatterns指定要过滤 的URL模式,也可使用属性value来声明.(指定要过滤的URL模式是必选属性)* @myblog http://blog.csdn.net/catoop/* @create 2016年1月6日*/ @WebFilter(filterName = "myFilter", urlPatterns = "/*") public class MyFilter implements Filter {private static final Logger LOGGER = LoggerFactory.getLogger(LogRecordAspect.class);@Overridepublic void init(FilterConfig config) throws ServletException {System.out.println("过滤器初始化");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {HttpServletRequest httpServletRequest = (HttpServletRequest) request;// 防止流读取一次后就没有了, 所以需要将流继续写出去ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest);String body = HttpHelper.getBodyString(requestWrapper);//如果请求Body为空异常处理if (StringUtils.isBlank(body)) { // LOGGER.error("非法请求, 没有APP_KEY, APP_SECRET"); chain.doFilter(request, response);return;}//开始处理请求体try {LOGGER.info("request:" + body);Map<String, Object> parameters = new ObjectMapper().readValue(body.replaceAll(""", "\""), new TypeReference<Map<String, Object>>() {});Object imReqeustEntityo = parameters.get("imReqeustEntity");if (imReqeustEntityo == null || "".equals(imReqeustEntityo)) {LOGGER.error("非法请求, 没有设备信息");} else {Map<String, String> imReqeustEntity = (Map<String, String>) imReqeustEntityo;if (imReqeustEntity == null || "".equals(imReqeustEntity)) {LOGGER.error("非法请求, 没有设备信息");}LOGGER.info("设备信息为: " + imReqeustEntity.toString());}chain.doFilter(requestWrapper, response);} catch (Exception e) {chain.doFilter(request, response);}}@Overridepublic void destroy() {System.out.println("过滤器销毁");}}
BodyReaderHttpServletRequestWrapper.java
package com.sinosoft.config;import org.slf4j.Logger; import org.slf4j.LoggerFactory;import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset;/*** 使用HttpServletRequestWrapper来包装HttpServletRequest* 在BodyReaderHttpServletRequestWrapper中初始化读取request的InputStream数据,以byte[]形式缓存在其中,然后在Filter中将request转换为包装过的request*/ public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {/*** 日志打印*/private static final Logger LOGGER = LoggerFactory.getLogger(BodyReaderHttpServletRequestWrapper.class);/*** 原加密请求体*/private final byte[] body;/*** 后解密请求体*/private final byte[] resetBody;/*** 处理request中的请求** @param request* @throws IOException*/public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {super(request);String rBody = HttpHelper.getBodyString(request);body = rBody.getBytes(Charset.forName("UTF-8"));//判断请求体是否为空 // if (!CommonUtil.isEmpty(rBody)) { // LOGGER.info("开始进行AES解密处理..."); // String aesBody = new String(body, "utf-8"); // LOGGER.info("请求加密报文:" + aesBody); // AES2 aes = new AES2(); // aesBody = aes.decrypt(aesBody); // resetBody = aesBody.getBytes(); // } else { // resetBody = body; // }resetBody = body;}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}/*** 重置request中的inputStream** @return i* @throws IOException ioe*/@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(resetBody);return new ServletInputStream() {@Overridepublic int read() throws IOException {return bais.read();}@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}};} }
HttpHelper.java
package com.sinosoft.config;import javax.servlet.ServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset;/*** Created with antnest-platform* User: chenyuan* Date: 12/24/14* Time: 10:39 AM*/ public class HttpHelper {/*** 获取请求Body** @param request* @return*/public static String getBodyString(ServletRequest request) {StringBuilder sb = new StringBuilder();InputStream inputStream = null;BufferedReader reader = null;try {inputStream = request.getInputStream();reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));String line = "";while ((line = reader.readLine()) != null) {sb.append(line);}} catch (IOException e) {e.printStackTrace();} finally {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}if (reader != null) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}return sb.toString();}}