Eine Anleitung zu HTTP-Cookies in Java

Ein Leitfaden für HTTP-Cookies in Java

1. Überblick

In diesem Artikel werden Operationen auf niedriger Ebene mit der Java-Netzwerkprogrammierung untersucht. Wir werden uns Cookies genauer ansehen.

Die Java-Plattform wird mit integrierter Netzwerkunterstützung geliefert, die im Paketjava.netenthalten ist:

import java.net.*;

2. HTTP-Cookies

Wenn ein Client eine HTTP-Anfrage an einen Server sendet und eine Antwort dafür erhält, vergisst der Server diesen Client. Wenn der Kunde das nächste Mal eine Anfrage stellt, wird er als völlig neuer Kunde angesehen.

Wie wir wissen, ermöglichen Cookies es jedoch, eine Sitzung zwischen dem Client und dem Server einzurichten, sodass sich der Server den Client über mehrere Anforderungsantwortpaare hinweg merken kann.

In diesem Abschnitt erfahren Sie, wie Sie Cookies verwenden, um die Client-Server-Kommunikation in der Java-Netzwerkprogrammierung zu verbessern.

Die Hauptklasse im Paketjava.net für den Umgang mit Cookies istCookieHandler. Es gibt andere Hilfsklassen und Schnittstellen wieCookieManager,CookiePolicy,CookieStore undHttpCookie.

3. DieCookieHandler Klasse

Betrachten Sie dieses Szenario. Wir kommunizieren mit dem Server umhttp://example.com oder mit einer anderen URL, die das HTTP-Protokoll verwendet. Das URL-Objekt verwendet eine Engine namens HTTP-Protokollhandler.

Dieser HTTP-Protokollhandler prüft, ob im System eine Standardinstanz vonCookieHandlervorhanden ist. Wenn dies der Fall ist, wird es aufgerufen, um die Zustandsverwaltung zu übernehmen.

Die KlasseCookieHandlerhat daher den Zweck, einen Rückrufmechanismus zum Nutzen des HTTP-Protokollhandlers bereitzustellen.

CookieHandler ist eine abstrakte Klasse. Es hat eine statischegetDefault()-Methode, die aufgerufen werden kann, um die aktuelleCookieHandler-Installation abzurufen, oder wir könnensetDefault(CookieHandler) aufrufen, um unsere eigene festzulegen. Beachten Sie, dass beim Aufrufen vonsetDefault einCookieHandler-Objekt systemweit installiert wird.

Es hat auchput(uri, responseHeaders) zum Speichern von Cookies im Cookie-Store. Diese Cookies werden aus den Antwortheadern der HTTP-Antwort von der angegebenen URI abgerufen. Es wird jedes Mal aufgerufen, wenn eine Antwort eingeht.

Eine verwandte API-Methode -get(uri,requestHeaders) ruft die unter dem angegebenen URI gespeicherten Cookies ab und fügt sie denrequetHeaders hinzu. Es wird aufgerufen, kurz bevor eine Anfrage gestellt wird.

Diese Methoden müssen alle in einer konkreten Klasse vonCookieHandler implementiert werden. An dieser Stelle ist die KlasseCookieManagerunsere Aufmerksamkeit wert. Diese Klasse bietet eine vollständige Implementierung derCookieHandler-Klasse für die meisten gängigen Anwendungsfälle.

In den nächsten beiden Abschnitten werden wir die KlasseCookieManageruntersuchen. zuerst im Standardmodus und später im benutzerdefinierten Modus.

4. Die StandardeinstellungCookieManager

Um ein vollständiges Cookie-Management-Framework zu haben, benötigen wir Implementierungen vonCookiePolicy undCookieStore.

CookiePolicy legt die Regeln für das Akzeptieren und Ablehnen von Cookies fest. Wir können diese Regeln natürlich an unsere Bedürfnisse anpassen.

Weiter -CookieStore macht genau das, was der Name andeutet. Es gibt Methoden zum Speichern und Abrufen von Cookies. Natürlich können wir auch hier den Speichermechanismus anpassen, wenn wir müssen.

Schauen wir uns zunächst die Standardeinstellungen an. So erstellen Sie die StandardwerteCookieHandler und legen sie als systemweiten Standard fest:

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

Wir sollten beachten, dass der StandardCookieStore einen flüchtigen Speicher hat, d.h. es lebt nur für die Lebensdauer der JVM. Um die Speicherung von Cookies dauerhafter zu gestalten, müssen wir sie anpassen.

Wenn es umCookiePolicy geht, ist die StandardimplementierungCookiePolicy.ACCEPT_ORIGINAL_SERVER. Dies bedeutet, dass das Cookie zurückgewiesen wird, wenn die Antwort über einen Proxyserver empfangen wird.

5. Ein benutzerdefiniertesCookieManager

Passen wir nun die StandardwerteCookieManageran, indem wir unsere eigene Instanz vonCookiePolicy oderCookieStore (oder beides) bereitstellen.

5.1. CookiePolicy

CookiePolicy bietet der Einfachheit halber einige vordefinierte Implementierungen:

  • CookiePolicy.ACCEPT_ORIGINAL_SERVER - Es können nur Cookies vom ursprünglichen Server gespeichert werden (Standardimplementierung).

  • CookiePolicy.ACCEPT_ALL - Alle Cookies können unabhängig von ihrer Herkunft gespeichert werden

  • CookiePolicy.ACCEPT_NONE - Es können keine Cookies gespeichert werden

Um einfach die aktuellenCookiePolicy zu ändern, ohne unsere eigenen zu implementieren, rufen wir diesetCookiePolicy in derCookieManager-Instanz auf:

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

Aber wir können noch viel mehr Anpassungen vornehmen. Wenn wir das Verhalten vonCookiePolicy.ACCEPT_ORIGINAL_SERVER kennen, nehmen wir an, dass wir einem bestimmten Proxyserver vertrauen und Cookies von diesem über dem ursprünglichen Server akzeptieren möchten.

Wir müssen dieCookiePolicy-Schnittstelle implementieren und dieshouldAccept-S-Methode implementieren. Hier ändern wir die Akzeptanzregel, indem wir den Domänennamen des ausgewählten Proxyservers hinzufügen.

Nennen wir die neue RichtlinieProxyAcceptCookiePolicy. Grundsätzlich lehnt es jeden anderen Proxyserver von seinershouldAccept-Implementierung ab, abgesehen von der angegebenen Proxy-Adresse, und ruft dann dieshouldAccept-Methode derCookiePolicy.ACCEPT_ORIGINAL_SERVER auf, um die Implementierung abzuschließen:

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
}

Wenn wir eine Instanz vonProxyAcceptCookiePolicy erstellen, übergeben wir zusätzlich zum ursprünglichen Server eine Zeichenfolge der Domänenadresse, von der wir Cookies akzeptieren möchten.

Anschließend legen wir diese Instanz als Cookie-Richtlinie für die Instanz vonCookieManagerfest, bevor wir sie als Standard-CookieHandler festlegen:

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

Auf diese Weise akzeptiert der Cookie-Handler alle Cookies vom ursprünglichen Server und auch die vonhttp://www.example.com.

5.2. CookieStore

CookieManager fügt die Cookies für jede HTTP-Antwort zuCookieStore hinzu und ruft für jede HTTP-Anforderung Cookies vonCookieStore ab.

Die Standardimplementierung vonCookieStorehat keine Persistenz, sondern verliert beim Neustart der JVM alle Daten. Eher wie RAM in einem Computer.

Wenn wir also möchten, dass sich die Implementierung vonCookieStorewie die Festplatte verhält und die Cookies bei JVM-Neustarts beibehalten, müssen wir den Speicher- und Abrufmechanismus anpassen.

Zu beachten ist, dass wir nach der Erstellung keineCookieStore-Instanz anCookieManager übergeben können. Unsere einzige Möglichkeit besteht darin, es während der Erstellung vonCookieManager zu übergeben oder einen Verweis auf die Standardinstanz zu erhalten, indem Sie neueCookieManager().getCookieStore() aufrufen und ihr Verhalten ergänzen.

Hier ist die Implementierung vonPersistentCookieStore:

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
}

Beachten Sie, dass wir einen Verweis auf die Standardimplementierung im Konstruktor abgerufen haben.

Wir implementierenrunnable, damit wir einen Shutdown-Hook hinzufügen können, der ausgeführt wird, wenn die JVM heruntergefahren wird. Innerhalb derrun-Methode speichern wir alle unsere Cookies im Speicher.

Wir können die Daten in eine Datei oder einen geeigneten Speicher serialisieren. Beachten Sie auch, dass wir im Konstruktor zuerst alle Cookies aus dem persistenten Speicher inCookieStore lesen. Diese beiden einfachen Funktionen machen die Standardwerte vonCookieStoreim Wesentlichen dauerhaft (auf vereinfachte Weise).

6. Fazit

In diesem Tutorial haben wir HTTP-Cookies behandelt und gezeigt, wie Sie programmgesteuert auf sie zugreifen und sie bearbeiten können.

Der vollständige Quellcode für den Artikel und alle Codefragmente finden Sie inGitHub project.