【问题标题】:Java proxy to intercept requestsJava代理拦截请求
【发布时间】:2015-05-16 22:55:34
【问题描述】:

我们想创建一个简单的 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.");
        }
    }

【问题讨论】:

    标签: java http tcp https proxy


    【解决方案1】:

    HTTPComponents 支持 HTTPS。另外,你不必自己编写套接字逻辑,就是这样。

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

    【讨论】:

    • 如果 OP 不为 HTTPS 做中间人,他将如何收集标头信息?标准 CONNECT 支持只需将 SSL 握手转发到服务器。
    猜你喜欢
    • 1970-01-01
    • 2013-11-10
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    • 2013-05-24
    • 2017-02-28
    • 2018-11-02
    • 2011-11-28
    相关资源
    最近更新 更多