Java代理拦截请求

时间:2015-03-14 13:30:40

标签: java http tcp https proxy

我们想创建一个简单的JAVA代理服务器,如果需要,它将从请求标头中收集信息。

我们已经实现了代理服务器,将我们的浏览器指向主机和端口,我们能够浏览使用简单HTTP协议的网站而不会出现问题。

我们支持GET和HEAD HTTP方法。

但是,使用HTTPS的站点会导致问题,因为这些站点会启动CONNECT方法,而我们无法获得安全连接,我们不确定在响应中发送什么。 (或者,如果我们能够监控从那一点开始的进一步请求。)

有什么建议吗?任何第三方实施都可以。但我们希望在同一过程中支持HTTP和HTTPS。

private void intercept() throws IOException {
        final DataInputStream socketInput = new DataInputStream(this.socket.getInputStream());
        final String httpMessage = RequestHeader.readHttpHeader(socketInput);
        //Request header is our own convenience file with utility methods that parses the request header.
        requestHeader = new RequestHeader(httpMessage);
        try {
            if ("GET".equals(requestHeader.getType()) || "HEAD".equals(requestHeader.getType())) {
                final URL url = new URL(requestHeader.getUrl());
                final HttpURLConnection connectionHttp = (HttpURLConnection) url.openConnection();
                connectionHttp.setRequestMethod(requestHeader.getType());
                // Send response back to client
                final DataInputStream dis = new DataInputStream(connectionHttp.getInputStream());

                // Add response header
                final StringBuilder sb = new StringBuilder();
                sb.append(requestHeader.getHttpVersion() + " " + connectionHttp.getResponseCode() + " "
                        + connectionHttp.getResponseMessage() + "\r\n");
                final Map<String, List<String>> map = connectionHttp.getHeaderFields();
                for (final Map.Entry<String, List<String>> entry : map.entrySet()) {
                    final String key = entry.getKey();
                    sb.append(key + " : "
                            + entry.getValue().toString().replace("[", "").replace("]", "").replace(",", " ") + "\r\n");
                }
                sb.append("\r\n");

                // Add response content
                final DataOutputStream socketOutput = new DataOutputStream(this.socket.getOutputStream());
                socketOutput.write(sb.toString().getBytes(), 0, sb.toString().getBytes().length);
                final byte[] data = new byte[(int) Short.MAX_VALUE];
                int index = dis.read(data, 0, (int) Short.MAX_VALUE);
                while (index != -1) {
                    socketOutput.write(data, 0, index);
                    index = dis.read(data, 0, (int) Short.MAX_VALUE);
                }
                socketOutput.flush();

                // NOTE this works perfectly fine for HTTP sites. We can intercept the communication properly.

            } else if ("CONNECT".equals(requestHeader.getType())) {
                // TODO establish connection
                // First line of header: CONNECT www.facebook.com:443 HTTP/1.1

                // We have tried to send back 200 ok response, but no further requests were sent.
            } else {
                //Nothing else is supported
                return;
            }
        } catch (final MalformedURLException e) {
            System.out.print("MalformedURLException " + e.getMessage());
            // return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
        } catch (final IOException e) {
            System.out.print("IOException " + e.getMessage());
            // return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
        } finally {
            System.out.println("Finished.");
        }
    }

1 个答案:

答案 0 :(得分:0)

HTTPComponents支持HTTPS。此外,您不必自己编写套接字逻辑,所以就是这样。

如果我没记错,HTTPS开箱即用,不需要任何奇怪的配置或特殊的ssl调用。