Guide sur les cookies HTTP en Java

Un guide pour les cookies HTTP en Java

1. Vue d'ensemble

Dans cet article, nous allons explorer les opérations de bas niveau avec la programmation réseau Java. Nous allons examiner de plus près les cookies.

La plate-forme Java est livrée avec une prise en charge réseau intégrée, intégrée dans le packagejava.net:

import java.net.*;

2. Cookies HTTP

Chaque fois qu'un client envoie une requête HTTP à un serveur et reçoit une réponse, le serveur oublie ce client. La prochaine fois que le client le demandera à nouveau, il sera considéré comme un tout nouveau client.

Cependant, les cookies, comme nous le savons, permettent d’établir une session entre le client et le serveur de telle sorte que le serveur puisse se souvenir du client entre plusieurs paires de réponses à une demande.

À partir de cette section, nous allons maintenant apprendre comment utiliser les cookies pour améliorer nos communications client-serveur dans la programmation réseau Java.

La classe principale du packagejava.net pour la gestion des cookies estCookieHandler. Il existe d'autres classes d'assistance et interfaces telles queCookieManager,CookiePolicy,CookieStore etHttpCookie.

3. La classeCookieHandler

Considérez ce scénario; nous communiquons avec le serveur àhttp://example.com, ou à toute autre URL utilisant le protocole HTTP, l'objet URL utilisera un moteur appelé gestionnaire de protocole HTTP.

Ce gestionnaire de protocole HTTP vérifie s'il existe une instanceCookieHandler par défaut dans le système. Si c'est le cas, il l'invoque pour prendre en charge la gestion de l'état.

Ainsi, la classeCookieHandler a pour but de fournir un mécanisme de rappel au profit du gestionnaire de protocole HTTP.

CookieHandler est une classe abstraite. Il a une méthode statiquegetDefault() qui peut être appelée pour récupérer l'installation actuelle deCookieHandler ou nous pouvons appelersetDefault(CookieHandler) pour définir la nôtre. Notez que l'appel desetDefault installe un objetCookieHandler à l'échelle du système.

Il a égalementput(uri, responseHeaders) pour enregistrer les cookies dans le magasin de cookies. Ces cookies sont récupérés à partir des en-têtes de réponse de la réponse HTTP à partir de l'URI donné. Il est appelé chaque fois qu'une réponse est reçue.

Une méthode API associée -get(uri,requestHeaders) récupère les cookies enregistrés sous l'URI donné et les ajoute auxrequetHeaders. Il est appelé juste avant qu'une demande ne soit faite.

Ces méthodes doivent toutes être implémentées dans une classe concrète deCookieHandler. À ce stade, la classeCookieManager mérite notre attention. Cette classe offre une implémentation complète de la classeCookieHandler pour la plupart des cas d'utilisation courants.

Dans les deux sections suivantes, nous allons explorer la classeCookieManager; d'abord dans son mode par défaut et plus tard en mode personnalisé.

4. LesCookieManager par défaut

Pour avoir un cadre complet de gestion des cookies, nous devons avoir des implémentations deCookiePolicy etCookieStore.

CookiePolicy établit les règles d'acceptation et de rejet des cookies. Nous pouvons bien sûr modifier ces règles pour répondre à nos besoins.

Ensuite -CookieStore fait exactement ce que son nom suggère, il dispose de méthodes pour enregistrer et récupérer les cookies. Naturellement, nous pouvons également modifier le mécanisme de stockage ici si nous en avons besoin.

Voyons d'abord les valeurs par défaut. Pour créer leCookieHandler par défaut et le définir comme valeur par défaut à l'échelle du système:

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

Nous devons noter que leCookieStore par défaut aura une mémoire volatile, c'est-à-dire il ne vit que pour la vie de la machine virtuelle. Pour avoir un stockage plus persistant des cookies, nous devons le personnaliser.

En ce qui concerneCookiePolicy, l'implémentation par défaut estCookiePolicy.ACCEPT_ORIGINAL_SERVER. Cela signifie que si la réponse est reçue via un serveur proxy, le cookie sera rejeté.

5. UnCookieManager personnalisé

Personnalisons maintenant lesCookieManager par défaut en fournissant notre propre instance deCookiePolicy ouCookieStore (ou les deux).

5.1. CookiePolicy

CookiePolicy fournit des implémentations prédéfinies pour plus de commodité:

  • CookiePolicy.ACCEPT_ORIGINAL_SERVER - seuls les cookies du serveur d'origine peuvent être enregistrés (implémentation par défaut)

  • CookiePolicy.ACCEPT_ALL - tous les cookies peuvent être enregistrés quelle que soit leur origine

  • CookiePolicy.ACCEPT_NONE - aucun cookie ne peut être enregistré

Pour changer simplement lesCookiePolicy actuels sans implémenter les nôtres, nous appelons lessetCookiePolicy sur l'instanceCookieManager:

CookieManager cm=new CookieManager();
cm.setCookiePolicy(CookiePolicy.ACCEPT_ALL);

Mais nous pouvons faire beaucoup plus de personnalisation que cela. Connaissant le comportement deCookiePolicy.ACCEPT_ORIGINAL_SERVER, supposons que nous faisons confiance à un serveur proxy particulier et que nous souhaitons accepter les cookies de celui-ci au-dessus du serveur d'origine.

Nous devrons implémenter l'interfaceCookiePolicy et implémenter la méthodeshouldAccept; c'est ici que nous modifierons la règle d'acceptation en ajoutant le nom de domaine du serveur proxy choisi.

Appelons la nouvelle politique -ProxyAcceptCookiePolicy. Il rejettera fondamentalement tout autre serveur proxy de son implémentationshouldAccept en dehors de l'adresse proxy donnée, puis appellera la méthodeshouldAccept desCookiePolicy.ACCEPT_ORIGINAL_SERVER pour terminer l'implémentation:

public class ProxyAcceptCookiePolicy implements CookiePolicy {
    private String acceptedProxy;

    public boolean shouldAccept(URI uri, HttpCookie cookie) {
        String host = InetAddress.getByName(uri.getHost())
          .getCanonicalHostName();
        if (HttpCookie.domainMatches(acceptedProxy, host)) {
            return true;
        }

        return CookiePolicy.ACCEPT_ORIGINAL_SERVER
          .shouldAccept(uri, cookie);
    }

    // standard constructors
}

Lorsque nous créons une instance deProxyAcceptCookiePolicy, nous transmettons une chaîne de l'adresse de domaine dont nous aimerions accepter les cookies en plus du serveur d'origine.

Nous définissons ensuite cette instance comme politique de cookie de l'instanceCookieManager avant de la définir comme CookieHandler par défaut:

CookieManager cm = new CookieManager();
cm.setCookiePolicy(new ProxyAcceptCookiePolicy("example.com"));
CookieHandler.setDefault(cm);

De cette façon, le gestionnaire de cookies acceptera tous les cookies du serveur d'origine ainsi que ceux dehttp://www.example.com.

5.2. CookieStore

CookieManager ajoute les cookies auCookieStore pour chaque réponse HTTP et récupère les cookies duCookieStore pour chaque requête HTTP.

L'implémentation par défaut deCookieStore n'a pas de persistance, elle perd plutôt toutes ses données lorsque la JVM est redémarrée. Plus comme de la RAM dans un ordinateur.

Donc, si nous voulons que notre implémentation deCookieStore se comporte comme le disque dur et conserve les cookies lors des redémarrages de la JVM, nous devons personnaliser son mécanisme de stockage et de récupération.

Une chose à noter est que nous ne pouvons pas passer une instanceCookieStore àCookieManager après la création. Notre seule option est de le passer lors de la création deCookieManager ou d'obtenir une référence à l'instance par défaut en appelant newCookieManager().getCookieStore() et en complétant son comportement.

Voici l'implémentation dePersistentCookieStore:

public class PersistentCookieStore implements CookieStore, Runnable {
    private CookieStore store;

    public PersistentCookieStore() {
        store = new CookieManager().getCookieStore();
        // deserialize cookies into store
        Runtime.getRuntime().addShutdownHook(new Thread(this));
    }

    @Override
    public void run() {
        // serialize cookies to persistent storage
    }

    @Override
    public void add(URI uri, HttpCookie cookie) {
        store.add(uri, cookie);

    }

    // delegate all implementations to store object like above
}

Notez que nous avons récupéré une référence à l'implémentation par défaut dans le constructeur.

Nous implémentonsrunnable afin que nous puissions ajouter un hook d'arrêt qui s'exécute lorsque la JVM s'arrête. Dans la méthoderun, nous conservons tous nos cookies en mémoire.

Nous pouvons sérialiser les données dans un fichier ou tout stockage approprié. Notez également qu'à l'intérieur du constructeur, nous lisons d'abord tous les cookies de la mémoire persistante dans lesCookieStore. Ces deux fonctionnalités simples rendent lesCookieStore par défaut essentiellement persistants (de manière simpliste).

6. Conclusion

Dans ce tutoriel, nous avons abordé les cookies HTTP et montré comment y accéder et les manipuler par programme.

Le code source complet de l'article et tous les extraits de code se trouvent dans lesGitHub project.