2013-06-02 60 views
1

我正嘗試使用java和jetty創建代理服務器。我已經管理連接到http(非安全的),但https有問題。在Java中使用SSL的HTTP代理

我一直在做的是:

private boolean handleConnect(HttpServletRequest req,HttpServletResponse response){ 
    String uri=req.getRequestURI(); 
    System.out.println("--Handle--Connect-"); 
    String port=""; 
    String host=""; 
    int c=uri.indexOf(":"); 
    if (c >= 0){ 
     port = uri.substring(c + 1); 
     host = uri.substring(0,c); 
     if (host.indexOf('/') > 0) 
      host = host.substring(host.indexOf('/') + 1); 
    } 
    boolean isBlocked; 
    isBlocked=false; 
    SocketChannel sock = null; 
    InputStream in=null; 
    OutputStream out=null; 
    try { 
     sock = SocketChannel.open(); 
     in=req.getInputStream(); 
     out=response.getOutputStream(); 

    } catch (IOException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } 
    try{ 
     InetSocketAddress inetAddress = new InetSocketAddress(host,req.getRemotePort()); 
     sock.connect(inetAddress); 
     InputStreamReader inputstreamreader = new InputStreamReader(req.getInputStream()); 
     BufferedReader bufferedreader = new BufferedReader(inputstreamreader); 

     OutputStreamWriter outputstreamwriter = new OutputStreamWriter(sock.socket().getOutputStream()); 
     BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter); 
     response.setStatus(200); 
     response.setHeader("Connection", req.getHeader("Connection")); 
     String string = null; 

     while ((string = bufferedreader.readLine()) != null) { 
       bufferedwriter.write(string); 
       bufferedwriter.flush(); 
     } 


     sock.configureBlocking(false); 
     sock.connect(new InetSocketAddress(host,Integer.parseInt(port))); 
     while(!sock.finishConnect()){ 
      // Wait for connecting 
     } 

      response.setStatus(200); 
      response.setHeader("Connection", req.getHeader("Connection")); 
      response.flushBuffer(); 

     ByteBuffer bb=ByteBuffer.allocate(1024*1024); 
     bb.clear(); 
     in.mark(0); 

     if(in.available()>0){ 

      byte by[]=new byte[in.available()]; 
      bb.put(by); 
       if(sock.isConnected()){ 
        sock.write(bb); 
       } 

     } 

    } 
    catch(Exception ex){ 
     ex.printStackTrace(); 
     isBlocked=true; 
     try { 
     // sock.close(); 
      throw new IOException("Hello World"); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     return false; 
    } 
    finally{ 
     try { 
      out.close(); 
      in.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
    return true; 
} 

我的問題是:

  1. 的代碼是不工作(Error code: ssl_error_rx_record_too_long)
  2. 當是關閉套接字連接,和什麼類型要使用的套接字。

在此先感謝。

更新的代碼:

private boolean handleConnect(HttpServletRequest req,HttpServletResponse response){ 
    String uri=req.getRequestURI(); 
    System.out.println("--Handle--Connect-"); 
    String port=""; 
    String host=""; 
    int c=uri.indexOf(":"); 
    if (c >= 0){ 
     port = uri.substring(c + 1); 
     host = uri.substring(0,c); 
     if (host.indexOf('/') > 0) 
      host = host.substring(host.indexOf('/') + 1); 
    } 
    boolean isBlocked; 
    isBlocked=false; 
    Socket sock = null; 
    IORedirect c2s, s2c; 

    // Make Asyncronous connection 
    try{ 
      sock=new Socket(host,Integer.parseInt(port)); 

      OutputStream os = response.getOutputStream(); 

      byte[] msg = new String("HTTP/1.0 200 Connection established\r\nProxy-agent: RPS-Proxy/1.0\r\n\r\n").getBytes(); 
      os.write(msg); 
      os.flush(); 

      c2s=new IORedirect(req.getInputStream(),sock.getOutputStream()); 
      c2s.setName("Client to Server"); 
      c2s.start(); 
      Thread.sleep(500); 

      s2c=new IORedirect(sock.getInputStream(), os); 
      s2c.setName("Server to Client"); 
      s2c.start(); 
      Thread.sleep(500); 
      System.err.println("A"); 

    } 
    catch(Exception ex){ 
     ex.printStackTrace(); 
     isBlocked=true; 
     try { 
      sock.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return false; 
    } 
    while(c2s.isAlive() || s2c.isAlive()){ 

    } 
    try { 
     sock.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    return true; 
} 
+0

下面是我們在Jetty 9中發佈的一個:http://download.eclipse.org/jetty/stable-9/xref/org/eclipse/jetty/proxy/ProxyServlet.html –

回答

2

我已經使用由碼頭提供的ConnectHandler解決了我的連接問題。

HandlerCollection coll=new HandlerCollection(); 
    ConnectHandler aa=new ConnectHandler(); 
    coll.addHandler(aa); 
    server.addConnector(http); 
    server.setHandler(coll); 

此代碼解決了Https + Http連接問題。我也可以使用身份驗證。

1

你不能寫一個正確的代理服務器作爲一個Servlet,對於一些原因。首先,您引入了太多的延遲,因爲在創建上游連接之前,請求是由servlet容器完全組裝的。

HTTP代理是一件非常簡單的事情,除非您需要查看請求和響應。您只需解析傳入的CONNECT命令,形成上游連接,然後開始同時在兩個方向複製字節。無論上游連接是HTTP還是HTTPS,代碼都是相同的。

爲了回答您的具體問題:

  1. 你應該從每一個同行,直到收到EOS閱讀。此時您應該關閉套接字到另一個對等端進行輸出。如果您已經關閉了套接字,那麼您應該關閉兩個套接字。

  2. 明文。傳入的HTTP CONNECT命令始終處於明文狀態,並且您不關心上游連接是什麼,因爲您只是複製字節。如果有必要的話,同行會協商SSL,但這與你無關。

+0

你是什麼意思'關機你的套接字到其他同行的輸出'你能否澄清。示例代碼? – progrrammer

+0

'Socket.shutdownOutput()'。 – EJP

+0

而我正在使用處理程序作爲碼頭中的代理。好嗎 ? – progrrammer