web-dev-qa-db-fra.com

Consigner toutes les interactions réseau de l'application Java

J'ai une application Java monstrueuse (un client du serveur d'applications peu connu GNUEnterprise) et son source, que je peux compiler après y avoir apporté quelques modifications. L'application utilise beaucoup le réseau et je dois surveiller chaque demande et chaque réponse. Je pourrais utiliser un renifleur comme Wireshark, mais l'application fonctionne avec son serveur via SSL. Par conséquent, ne pas connaître la clé privée du certificat SSL, le trafic capturé est plutôt inutile.

Que puis-je faire pour que chaque demande et chaque réponse soient enregistrées depuis l'application elle-même? J'ai besoin de voir tous les en-têtes envoyés et reçus. Je ne veux pas modifier tout le code responsable de l'interaction réseau. Ce que je veux, c'est mettre un code comme

Network.setDefaultLogger(myCustomLoggerInstance);

quelque part près du début de l'application, puis dans la myCustomLoggerInstance faire tout la journalisation dont j'ai besoin.

De plus, étant donné que toutes les opérations réseau sont effectuées avec URLConnections, je peux obtenir les en-têtes de réponse avec con.getHeaderFields() et les en-têtes de demande avec con.getRequestProperties(). Mais pourquoi les cookies ne sont pas là? Comment vider les cookies envoyés et reçus de la même manière?

EDIT: Ce que j'essaie d'atteindre, c'est d'imiter la communication de l'application RPC avec son serveur via SSL, en utilisant, par exemple, curl. Pour cela, je dois obtenir un journal détaillé du trafic réseau de l'application.

12
Hnatt

Ne pouvez-vous pas utiliser un serveur proxy de journalisation, par exemple http://www.charlesproxy.com/ ou http://fiddler2.com/ ? Charles Proxy peut également décoder les requêtes AMF, Fiddler est le champion de l'interception SSL.

IIRC vous pouvez définir les propriétés système http.proxyHost et http.proxyPort sur 127.0.0.1 et 8888, et les connexions Java URLC se connecteront automatiquement via votre serveur proxy de journalisation, ce qui vous donnera une vue agréable de votre trafic HTTP.

Ou, si vous souhaitez pouvoir rejouer la communication, utilisez le proxy HTTP JMeter, qui enregistre dans un format adapté à la réexécution. Il a également un support intégré pour la gestion des cookies.

Si l'application utilise les services Web de Nice, SoapUI dispose également d'un proxy de surveillance qui intercepte les appels de services Web pour lesquels vous avez importé le WSDL.

14
Geert Pante

Un moyen rapide de consigner tout le trafic SSL consiste à démarrer Java avec:

-Djavax.net.debug=all

Ou définissez-le comme une propriété système:

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

Préparez vous. Standard out obtient NOISY si vous faites cela!

(* Remarque: enregistre uniquement le trafic et les informations de débogage SSL (poignée de main, etc.). Les sockets ordinaires ne sont pas enregistrés.)

13
Julius Musseau

J'ai creusé un peu plus loin, et apparemment, HttpURLConnection est livré avec Java.util.logging activé par défaut.

Voir les questions connexes: Java: demande d'affichage d'une connexion HttpURLConnection avant l'envoi et Comment activer la journalisation filaire pour un trafic Java HttpURLConnection?

Java.util.logging est la tentative (échouée) de Sun visant à normaliser les fournisseurs de journalisation dans Java 1.4. Vous pouvez le relier à SLF4J via le module jul-to-slf4j si vous souhaitez éviter de modifier les propriétés du système.

Mais je préférerais quand même un proxy Fiddler ou JMeter :-)

2
Geert Pante

Je veux juste poster un extrait de code que vous pouvez utiliser au point de départ. Je n'ai pas d'enregistreur "global", mais avec de petites modifications du code existant, vous pouvez atteindre votre objectif. Je me connecte sur une sortie standard, car votre problème peut être divisé en deux parties: obtenir les informations à partir de UrlConnection et les stocker pour référence ultérieure.

Ce code enregistre la demande:

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();
}

}

enregistrer toutes ces données dans un ou plusieurs fichiers n'est pas difficile. Si vous croyez que je suis sur la bonne voie pour votre problème, je serais heureux de modifier la réponse avec d'autres détails si nécessaire.

2
giampaolo

Si vous souhaitez enregistrer le trafic réseau et que vous avez des objets URLConnection, le problème est déjà résolu!
Si vous souhaitez vous connecter au niveau d'un flux, vous devez écrire un petit wrapper sur vos flux d'E/S et consigner toutes les données avant de les transférer vers des couches réseau inférieures. Sinon, vous pouvez utiliser directement des objets de connexion pour obtenir informations requises et connectez-vous.
Pour gérer les cookies, vous devez utiliser Java.net.HttpCookie qui est introduit dans Java 6. Il vous suffit de créer une instance de CookieManager et de la définir comme gestionnaire de cookies par défaut:

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

& vous pouvez l'utiliser pour gérer les cookies de connexion!

1
Ehsan Khodarahmi