目前app测试时我们需要对接口数据进行抓包,对于app的抓包,我们可以使用很多现成的工具,比如fiddler、wireshark、charles等,基本上可以满足要求,但是对于一些定制化的需求,比如说:我们需要将抓包的数据进行篡改后再发送到服务器,或者对请求的数据新增标志字段以便定位问题,或者更多需要更改数据的需求,传统抓包工具已经很难实现,需要我们探索新的方式方法。

    我们知道,一般的抓包工具都是使用代理的方式来截取请求,然后以ui的方式展现出来,我们本次也直接使用这种代理的方式来实现抓包,然后对抓取的包进行数据的重组和处理后再发送到原本请求的服务器获取结果返回给app即可。整个流程如下(此流程仅适用于http、https协议):








说明:代理服务器抓取到app到服务器之间的包,进行解包之后,对数据进行处理(更改或者新增)后再次进行数据封包,将封包后的数据发送到原服务器之后将数据返回给app即可,这期间我们在解包之后可以看到数据的具体信息。

   整个系统最核心的内容无疑为代理服务器,甚至有些人对数据的解包和封包和再次发送感觉实现起来很难。如果app的请求为http协议,其实我们可以使用现成的工具,最直接的就是将代理服务器伪装成一个web服务器,app发送给web服务器的数据可以直接被web服务器解包,之后可以使用httpclient再次模拟客户端做封包操作发送给app:

数据拦截:web拦截器

数据解包:servlet(request)

数据处理:自助java类

数据再封包和发送:httpclient

数据的接收:httpclient

数据返回app:servlet(response)


整个流程变为:







下面我们从代码层面来说明整个过程:

1.搭建一个web的服务器环境

2.写一个拦截器








3.代理服务器代码

packagecom.pingan.testcloud.units;
/**
* ClassName:LoginFilter
*
* @Description:过滤器,白名单里所有接口都要先经过此过滤器,白名单请在web.xml中设置
* @author dingjingjing058
* @date 2016年5月13日
*/
importjava.io.IOException;
importjava.io.PrintWriter;
importjava.net.URLDecoder;
importjava.net.URLEncoder;
importjava.util.ArrayList;
importjava.util.Enumeration;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjavax.servlet.http.HttpSession;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importcom.pingan.testcloud.httphelper.BasicParameter;
import com.pingan.testcloud.httphelper.HttpClientHelper;
importcom.pingan.testcloud.httphelper.ResponseParameter;
public classLoginFilter implements Filter {
publicLogger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@SuppressWarnings("rawtypes")
@Override
public void doFilter(ServletRequest req,ServletResponse res, FilterChain chain)
throws IOException,ServletException {
HttpServletRequest request =(HttpServletRequest) req;
HttpServletResponse response =(HttpServletResponse) res;
request.setCharacterEncoding("UTF-8");
//获得用户请求的URI,并进行截取
String url= request.getRequestURI();
String[] path =url.split("/");
// System.out.println(path);
Enumerationenu=request.getParameterNames();
String paraString="";
while(enu.hasMoreElements()){
StringparaName=(String)enu.nextElement();
paraString=paraString+paraName+":"+request.getParameter(paraName)+"";
}
logger.info("用户请求地址为:"+url+"请求参数为:"+paraString);
if(ConfigReader.getWhiteListMap().get(path[path.length-1])==null){//如果不在白名单,则进行如下校验
String method=request.getMethod();
if(method.equals("POST"))
method="post";
elseif(method.equals("GET"))
method="get";
BasicParameter bp1 = newBasicParameter(url,"get","FILTER");
enu=request.getParameterNames();
while(enu.hasMoreElements()){
String paraName=(String)enu.nextElement();
bp1.addParamters(paraName,request.getParameter(paraName));
Enumerationen=request.getHeaderNames();
Map headers=newHashMap();
while(en.hasMoreElements()){
//取出信息名
String name=(String)en.nextElement();
//取出信息值
String value=request.getHeader(name);
headers.put(name, value);
}
bp1.setHeaders(headers);
}
List rps= new ArrayList();
try {
HttpClientHelper client=newHttpClientHelper(request.getServerName(),request.getServerPort(),"http");
client.addHttpRequest(bp1);
rps=client.run();
} catch (Exception e1) {
// TODO Auto-generatedcatch block
e1.printStackTrace();
}
for(Map.Entryen:rps.get(0).getHeaders().entrySet())
{
response.addHeader(en.getKey(),en.getValue());
}
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
PrintWriter out =response.getWriter();
out.print(rps.get(0).getRespdata());
out.flush();
out.close();
//response.sendRedirect("./login.html");
//chain.doFilter(request,response);
//已经登陆,继续此次请求
}
else
{
//在白名单里,继续此次请求
chain.doFilter(request,response);
}
}
@Override
public void init(FilterConfig config)throws ServletException {
}
}


注意:

1.代码中使用了httpclient,具体代码封装请参加技术文档。

2.对于解包后的数据操作未做详细讲解,可以参考sevlet技术文档。


最后,对手机设置网络代理,代理指向web服务器的ip和端口,试试效果吧。