大家都知道大名鼎鼎的BurpSuite代理神器,對于抓取HTTP請求非常好用,偶然,一朋友問我Java應該如何去編寫代理服務器(因為他想做某些東西),有沒有相關的API 去實現,我想說,差不多你能想到的,JAVA都可以做到,沒有任何一門成熟的語言是垃圾的。
在編寫代理服務器之前,首先應該明白一點,Java的代理機制,如圖1-1所示。
那么Java就處于中間這層代理服務器,代理服務器所作的事情如下:
1、接收客戶端請求,進行處理,然后發送給服務端
2、接收服務端響應,進行處理,然后發送給客戶端
這樣,就更清晰了,Java給我們提供了代理的API為,java.net.Proxy類。此類表示代理設置,通常為類型(http、socks)和套接字地址。Proxy 是不可變對象。
也就是說Java可以制作高級協議的代理,如 HTTP 或 FTP。也可以制作SOCKS(V4 或 V5)代理。
在基本的概念說完之后,來實際操作一把,分為兩個步驟,第一部分,讓JAVA程序使用代理服務器,第二步部分,讓我們的Java程序像BurpSuite一樣,來做一個HTTP的代理服務器吧。
首先,使用到了URL類,HttpURLConnection類及其我們的代理類Proxy類。他們都位于java.net包中。
第一步:生成代理,指定端口為8888:
Proxy?proxy?=?null?;
proxy?=?new?Proxy(Proxy.Type.HTTP,new?InetSocketAddress("127.0.0.1",8888));??//?實例化本地代理對象,端口為8888
第二步:使用URLConnection類進行連接www.moonsos.com
URL?url?=?new?URL("http://www.moonsos.com");??//實例化米安網URL類
HttpURLConnection?action?=?(HttpURLConnection)url.openConnection(proxy);??//使用代理打開網頁
第三步:打開URL,并且讀取HTML源碼
HttpURLConnection?action?=?(HttpURLConnection)url.openConnection(proxy);??//使用代理打開網頁
InputStream?in?=action.getInputStream();
BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(in,"UTF-8"));
StringBuilder?sb?=?new?StringBuilder();
String?lin?=?System.getProperty("line.separator")?;
for(String?temp?=?br.readLine()?;?temp!=null;temp?=?br.readLine()?){
sb.append(temp+lin);
}
br.close();
in.close();
System.out.println(sb);
效果執行圖,如圖1-2所示。
完整代碼示例如下:
import?java.net.*?;
import?java.io.*?;
public?class?ProxyTest{
public?static?void?main(String?args[])throws?Exception{
Proxy?proxy?=?null?;
proxy?=?new?Proxy(Proxy.Type.HTTP,new?InetSocketAddress("127.0.0.1",8888));??//?實例化本地代理對象,端口為8888
URL?url?=?new?URL("http://www.moonsos.com");
HttpURLConnection?action?=?(HttpURLConnection)url.openConnection(proxy);??//使用代理打開網頁
InputStream?in?=action.getInputStream();
BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(in,"UTF-8"));
StringBuilder?sb?=?new?StringBuilder();
String?lin?=?System.getProperty("line.separator")?;
for(String?temp?=?br.readLine()?;?temp!=null;temp?=?br.readLine()?){
sb.append(temp+lin);
}
br.close();
in.close();
System.out.println(sb);
}
}
第一部分我們學會了Java如何使用代理程序,那么第二部分就看Java制作代理服務器。
第一步,生成Socket類,作為代理服務器
ServerSocket?server??=?new?ServerSocket(8888);??//建立本地代理服務器,端口為8888
第二步,等待連接,也就是等待使用代理程序的用戶進入,如果沒有用戶進入那么,將會一直在此等待。
Socket socket =server. accept(); ? //等待客戶端連接
第三步,當用戶進來后,查看用戶數據發送的請求,這里新做了一個ActionScoket類,多線程,專門用來處理Scoket輸入流,代碼如下所所示。
ServerSocket?server??=?new?ServerSocket(8888);
while(true){
Socket?socket?=?server.accept();
ActionSocket?ap?=?new?ActionSocket(socket);
ap.start();
}
ActionSocket代碼如下:
class?ActionSocket?extends?Thread{
private?Socket?socket?=?null?;
public?ActionSocket(Socket?s){
this.socket?=?s?;
}
public?void?run(){
try{
this.action()?;
}catch(Exception?e){
e.printStackTrace();
}
}
public?void?action()?throws?Exception?{
if?(this.socket?==?null){
return?;
}
BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(this.socket.getInputStream()));
for(String?temp?=?br.readLine()?;?temp!=null;temp?=?br.readLine()?){
System.out.println(temp);
}
br.close();
}
}
完成代碼如下:
import?java.net.*?;
import?java.io.*?;
class?ActionSocket?extends?Thread{
private?Socket?socket?=?null?;
public?ActionSocket(Socket?s){
this.socket?=?s?;
}
public?void?run(){
try{
this.action()?;
}catch(Exception?e){
e.printStackTrace();
}
}
public?void?action()?throws?Exception?{
if?(this.socket?==?null){
return?;
}
BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(this.socket.getInputStream()));
for(String?temp?=?br.readLine()?;?temp!=null;temp?=?br.readLine()?){
System.out.println(temp);
}
br.close();
}
}
public?class?ServerPrxoy{
public?static?void?main(String?args[])throws?Exception{
ServerSocket?server??=?new?ServerSocket(8888);
while(true){
Socket?socket?=?server.accept();
ActionSocket?ap?=?new?ActionSocket(socket);
ap.start();
}
}
}
給火狐,搜狗等瀏覽器配置代理,如圖1-3所示:
OK,配置完畢,進行訪問http://www.moonsos.com,可以發現我們寫的小程序已經能夠進行抓取到HTTP協議信息,如圖1-4所示。
當獲取HTTP請求之后,我想后面的東西就不用說了吧。無非就是對HTTP請求進行分析,封裝。然后在時候Socket發送。獲取到信息之后,在使用當前的Socket以打印流的方式輸出到瀏覽器。