说到篡改请求,其实就是篡改底层的一些数据包,就是替换数据包里面的一些数据而已。
前面我们开发了一个HTTP代理服务器,在里面我们是通过转发的方式来实现的,说白了,就是所有的数据都经过了这个代理服务器进行转发,既然数据都了我们的手上了,那么截取,发到别的地方,或者篡改,还不是手到擒来的事。
下面我就实现一个简单的篡改功能,希望大家举一反三。对大家的学习有帮助。
看过HTTP请求代理服务器博文的同学继续往下面看,没看过的同学请先看那片博文。
首先我们需要一个Map<String,String> ,这个里面保存的就是我们需要替换的字符串,其中Key代表原本的字符串,value代表需要替换的字符串。
这个私有对象是保存在 HTTPServerThread 类里面的
private static Map<String, String> filter = new HashMap<String, String>();
还有就是添加一个替换的方法,和一个设置上面map 的方法
/**
* 替换数据 - 篡改数据
* @param buf
*/
private byte[] replease(byte[] buf) {
String tmp = new String(buf);
for (String key : filter.keySet()) {
if(tmp.contains(key)) {
tmp=tmp.replace(key,filter.get(key));
}
}
return tmp.getBytes();
}
public static void put(String str, String rep) {
filter.put(str, rep);
}
然后就是改造我们的doGet方法,将我们的replease方法加进去
/**
* 处理GET请求
* @param buf 缓冲区
* @param creadlen 客户端读取buf的长度
* @param sin 服务端输入流
* @param cout 客户端输出流
* @param sout 服务端输出流
* @return
* @throws IOException
*/
private int doGet(byte[] buf, int creadlen, DataInputStream sin, DataOutputStream cout, DataOutputStream sout) throws IOException {
int sreadlen;// 如读到 GET 请求,向外网发出 GET 请求
System.out.println("[get] >> " + new String(buf));
write(buf, creadlen, sout);
while ((sreadlen = sin.read(buf, 0, 10000))!=-1) { // 循环
try {
if (sreadlen > 0) {
//替换内容
byte [] tmp = replease(buf);
write(tmp, tmp.length, cout);
}
} catch (Exception e) {
break;
} // 异常则退出
}
return sreadlen;
}
接下来替换post方法
/**
* 处理POST 请求
* @param buf 数据缓存区
* @param creadlen 客户端读取的buf的长度
* @param sreadlen 服务端读取的buf的长度
* @param cin 客户端输入流
* @param sin 服务端输入流
* @param cout 客户端输出流
* @param sout 服务端输出流
* @throws IOException
*/
private void doPost(byte[] buf, int creadlen, int sreadlen, DataInputStream cin, DataInputStream sin, DataOutputStream cout, DataOutputStream sout) throws IOException {
write(buf, creadlen, sout);
// 建立线程 , 用于从外网读数据 , 并返回给内网客户端
HTTPChannel thread1 = new HTTPChannel(sin, cout);
while ((sreadlen = cin.read(buf, 0, 10000))!=-1) { // 循环
try {
System.out.println("post>>"+new String(buf));
if (sreadlen > 0) { // 读到数据 , 则发送给外网
write(replease(buf), sreadlen, sout);
}
} catch (Exception e1) {
break;
}
}
}
到现在为止,我们就可以替换请求数据包里面的数据了
需要替换什么直接put到Map里面就可以了。
至于截取数据包转发到其地址,就是在发送数据的时候,顺带发一份到其他的地址,还是很简单的,就留给你们自己实现咯。