2013-08-29 36 views
10

Tôi có một ứng dụng Java khổng lồ (một máy khách ứng dụng ít được biết đến GNUEnterprise) và nguồn của nó, mà tôi có thể biên dịch lại sau khi thực hiện một số thay đổi. Ứng dụng sử dụng mạng rất nhiều và tôi cần theo dõi từng yêu cầu và phản hồi. Tôi có thể sử dụng một trình thám thính như Wireshark, nhưng ứng dụng hoạt động với máy chủ của nó qua SSL, do đó, không biết khóa riêng tư của chứng chỉ SSL bất kỳ lưu lượng truy cập sniffed là khá vô ích.Ghi lại tất cả các tương tác mạng của ứng dụng Java

Tôi có thể làm gì để thực hiện mọi yêu cầu và phản hồi được đăng nhập từ chính ứng dụng? Tôi cần xem tất cả các tiêu đề đã gửi và nhận. Tôi không muốn thay đổi tất cả các mã chịu trách nhiệm về tương tác mạng. Những gì tôi muốn là đặt một mã như

Network.setDefaultLogger(myCustomLoggerInstance); 

ở đâu đó gần bắt đầu ứng dụng và sau đó trong myCustomLoggerInstance thực hiện tất cả nhật ký tôi cần.

Ngoài ra, với tất cả các hoạt động mạng được thực hiện với URLConnection s, tôi có thể nhận tiêu đề phản hồi với con.getHeaderFields() và yêu cầu tiêu đề với con.getRequestProperties(). Nhưng tại sao không có cookie? Làm thế nào để đổ cookie đã gửi và nhận theo cùng một cách?

EDIT: Điều tôi đang cố gắng tiếp cận là bắt chước giao tiếp của ứng dụng RPC với máy chủ của nó qua SSL, giả sử sử dụng curl. Đối với điều này tôi cần phải có được nhật ký chi tiết về lưu lượng mạng của ứng dụng.

+0

tôi sẽ sửa đổi 'OpenJDK', thực hiện các chức năng logger đề cập sau đó sniff các thông tin liên lạc tại thư viện cấp độ. – auselen

+0

@auselen quá hacky. Nếu không có cách nào để làm điều này trên cấp ứng dụng (và nó có vẻ như vậy), tôi sẽ tốt hơn dính vào một máy chủ proxy đăng nhập bên ngoài, như đề nghị của greyfairer. – Hnatt

Trả lời

11

Bạn không thể sử dụng máy chủ proxy ghi nhật ký, ví dụ: http://www.charlesproxy.com/ hoặc http://fiddler2.com/? Charles Proxy cũng có thể giải mã các yêu cầu AMF, Fiddler là nhà vô địch cho việc chặn SSL.

IIRC bạn có thể đặt thuộc tính hệ thống http.proxyHost và http.proxyPort thành 127.0.0.1 và 8888 và java URLConnections sẽ tự động kết nối qua máy chủ proxy ghi nhật ký của bạn và bạn có giao diện HTTP tốt đẹp.

Hoặc, nếu có ý định có thể phát lại liên lạc, hãy sử dụng JMeter HTTP Proxy, bản ghi này ở định dạng phù hợp để phát lại. Nó cũng được hỗ trợ sẵn để xử lý cookie.

Nếu ứng dụng sử dụng các dịch vụ web tốt đẹp, SoapUI cũng có một giám sát proxy chặn các cuộc gọi dịch vụ web mà bạn đã nhập WSDL.

+0

Ồ, và nó cũng có lưu lượng truy cập SSL. Tôi chắc chắn sẽ thử điều này. – Hnatt

+0

Để cho phép SSL Sniffing, bạn cũng cần phải hack cửa hàng ủy thác java của mình, xem: http: // stackoverflow.com/questions/8549749/how-to-capture-https-với-fiddler-in-java – greyfairer

+0

ứng dụng tôi đang xử lý đã xử lý điều đó. Nó có một lớp sử dụng 'HttpsURLConnection.setDefaultHostnameVerifier' và' .setDefaultSSLSocketFactory' để tin cậy tất cả các chứng chỉ. Tôi sẽ chấp nhận câu trả lời của bạn nếu không có giải pháp cấp ứng dụng được đề xuất, bởi vì nó thực sự làm những gì tôi muốn, mặc dù theo một cách khác. Tôi cũng tìm thấy một sự thay thế miễn phí cho Charles gọi là [webscarab] (https://www.owasp.org/index.php/Category:OWASP_WebScarab_Project), chạy trên Linux không giống như Fiddler. – Hnatt

2

Tôi chỉ muốn đăng một đoạn mã mà bạn có thể sử dụng tại điểm bắt đầu. Tôi không có trình ghi nhật ký "toàn cầu" nhưng với những thay đổi nhỏ đối với mã hiện tại, bạn có thể đạt được mục tiêu của mình. Tôi "đăng nhập" trên đầu ra tiêu chuẩn, kể từ khi vấn đề của bạn có thể được chia thành hai phần: nhận được thông tin từ UrlConnection và lưu trữ nó để tham khảo thêm.

Mã này ghi lại yêu cầu:

public class URLConnectionReader { 

    public static void main(String[] args) throws Exception { 
    URL oracle = new URL("http://www.google.com/"); 
    URLConnection yc = oracle.openConnection(); 

    String headerName = null; 
    for (int i = 1; (headerName = yc.getHeaderFieldKey(i)) != null; i++) { 
    if (headerName.equals("Set-Cookie")) { 
     String cookie = yc.getHeaderField(i); 
     System.out.println("Cookie :: " + cookie); 
    } else { 
     System.out.println("Header: "+ yc.getHeaderField(i)); 
    } 
    } 

    BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream())); 
    String inputLine; 
    while ((inputLine = in.readLine()) != null) 
    System.out.println(inputLine); 
    in.close(); 
} 

}

tiết kiệm tất cả các dữ liệu này để một hoặc nhiều file không phải là khó khăn. Nếu bạn tin rằng tôi đang đi đúng hướng cho bạn, tôi sẽ vui lòng chỉnh sửa câu trả lời với các chi tiết khác nếu cần.

+0

Cảm ơn, nhưng có vẻ như 'getHeaderFieldKey (i)' và 'getHeaders()' vì một số lý do bỏ qua các tiêu đề 'Set-Cookie'. Dù sao, tôi đang tìm một cách để thiết lập một logger mạng toàn cầu cho toàn bộ ứng dụng, không phải đặt đoạn mã ở khắp mọi nơi trên mạng tương tác diễn ra. Ngoài ra, với giải pháp của bạn, tôi phải đọc kết nối hai lần. – Hnatt

+0

Và dĩ nhiên việc lưu nhật ký vào một tệp không phải là vấn đề. Vì vậy, tôi muốn chia câu hỏi của tôi trong hai phần sau đây: 1) Thiết lập logger toàn cầu; 2) Ghi lưu lượng truy cập mà không cần đọc hoặc gửi phản hồi và yêu cầu hai lần. – Hnatt

+0

Rất tiếc, xấu của tôi. Nếu bạn gọi 'getHeaders()' sau khi gửi một yêu cầu trên một cá thể 'URLConnection', nó không mở luồng đọc lần thứ hai, và bạn thực sự có thể thấy các tiêu đề' Set-Cookie' ở đó. Vì vậy, 1 cho bạn, xin lỗi cho tất cả các tuyên bố sai. Những gì còn lại là một cách để thiết lập proxy cho tất cả các kết nối mạng (tôi có nghĩa là OOP proxy mẫu, không phải là một máy chủ proxy). – Hnatt

2

Tôi đào thêm một chút, và rõ ràng, HttpURLConnection đi kèm với java.util.logging được bật theo mặc định.

Xem các câu hỏi liên quan: Java: Display request of an HttpURLConnection before sendingHow to enable wire logging for a java HttpURLConnection traffic?

java.util.đăng nhập là nỗ lực của Sun (thất bại) khi chuẩn hóa các nhà cung cấp đăng nhập trong Java 1.4. Bạn có thể kết nối nó với SLF4J thông qua mô-đun jul-to-slf4j nếu bạn muốn tránh tinh chỉnh các thuộc tính hệ thống.

Nhưng tôi vẫn muốn Fiddler hoặc JMeter proxy mặc dù :-)

+0

Không thể quản lý để làm cho nó hoạt động. Bây giờ tôi cũng thích một máy chủ proxy. – Hnatt

0

Nếu bạn muốn đăng nhập lưu lượng mạng & bạn có các đối tượng URLConnection thì vấn đề đã được giải quyết!
Nếu bạn muốn đăng nhập ở mức luồng, bạn cần phải viết một trình bao bọc nhỏ trên đầu luồng I/O & ghi lại tất cả dữ liệu trước khi chuyển chúng sang các lớp mạng thấp hơn, nếu không bạn có thể sử dụng trực tiếp đối tượng kết nối để nhận thông tin được yêu cầu & đăng nhập chúng.
Đối với việc quản lý cookie, bạn nên sử dụng java.net.HttpCookie được giới thiệu trong java 6. Chỉ có điều bạn phải làm là để tạo ra một thể hiện của CookieManager & thiết lập nó như quản lý cookie mặc định:

CookieManager cookieManager = new CookieManager(); 
CookieHandler.setDefault(cookieManager); 

& bạn có thể sử dụng nó để quản lý cookie kết nối!

+0

Ban đầu tôi đã tìm kiếm một cái gì đó giống như đối tượng quản lý cookie toàn cầu này, chỉ cho tất cả các hành động mạng, nhưng sau đó tôi quyết định sử dụng máy chủ proxy đăng nhập cục bộ là đủ. Tôi thậm chí không cần can thiệp vào mã nguồn trong trường hợp này. Nhân tiện, người ta có thể sử dụng tùy chỉnh 'CookieManager' để đăng nhập các tiêu đề yêu cầu đến và đi, không chỉ cookie. Các phương thức 'get' và' put' của 'CookieManager' có' requestHeaders' và 'responseHeaders' tương ứng như đối số thứ hai của chúng trong kiểu' List '. Tôi tự hỏi chỉ khi các phương pháp này được gọi ở mọi yêu cầu và phản hồi hoặc chỉ khi cookie được sử dụng. – Hnatt

9

Một cách nhanh chóng để đăng nhập tất cả lưu lượng SSL là để khởi động java với:

-Djavax.net.debug=all 

Hoặc thiết lập nó như một thuộc tính hệ thống:

System.setProperty("javax.net.debug","all"); 

Brace mình. Tiêu chuẩn ra được NOISY nếu bạn làm điều này!

(* Lưu ý:.. Chỉ ghi giao thông SSL và SSL thông tin gỡ lỗi (bắt tay, vv) ổ cắm thông thường chưa đăng nhập)