Verbindung zur Sitzung in Java und Python. HttpURLConnection und CookieManager (Java). Anfragen (Python)

Angenommen, wir müssen eine Verbindung zu einem Server herstellen, uns anmelden und eine Sitzung verwalten. Im Browser sieht es so aus:



  1. Eine leere GET-Anfrage wird an die Adresse http: // localhost: 8080 / login gesendet.
  2. Der Server sendet ein Formular zum Ausfüllen des Logins und des Passworts sowie ein Cookie des Formulars "JSESSIONID = 094BC0A489335CF8EE58C8E7846FE49B".
  3. Nach dem Eingeben des Benutzernamens und des Passworts wird eine POST-Anfrage mit dem zuvor empfangenen Cookie an den Server gesendet. Die Zeile im Ausgabestream lautet "Benutzername = Fox & Passwort = 123". In den Headern wird zusätzlich "Inhaltstyp: application / x-www-form-urlencoded" angegeben.
  4. Als Antwort sendet uns der Server ein neues Cookie mit einer neuen "JSESSIONID =". Es leitet sofort per GET-Anfrage mit einem neuen Cookie zu http: // localhost: 8080 / um.
  5. Anschließend können Sie den Rest der Server-API sicher verwenden und das letzte Cookie in jeder Anforderung übergeben.


Mal sehen, wie dies in Java und Python implementiert werden kann.







Inhalt





Python-Implementierung. Anfragen



Bei der Auswahl einer Bibliothek für die Arbeit mit einem Netzwerk in Python empfehlen die meisten Websites die Anforderungsbibliothek , was den Slogan vollständig rechtfertigt:

HTTP für Menschen
Das ganze Problem wird durch das folgende Skript gelöst:



import requests
session = requests.session()  # 
url = "http://localhost:8080/login"
session.get(url)   # cookie
data = {"username": "Fox", "password": "123"} 
response = session.post(url, data=data) #


Beachten Sie, dass die Manipulation von Cookies und Weiterleitungen wie in einem Browser unter der Haube erfolgt. Es kann auch beachtet werden, dass Sie zwei Verbindungen gleichzeitig aktiv halten können , wenn Sie eine andere Variable session2 erhalten .



Java-Implementierung, HttpURLConnection und CookieManager



Die Suche nach einer Bibliothek für die Vernetzung in Java führt zu mehreren Bibliotheken gleichzeitig.



Zum Beispiel java.net , Apache HttpClient und OkHttp3 .



Ich habe mich für HttpURLConnection (java.net) entschieden. Die Vorteile dieser Bibliothek sind, dass es sich um eine " out of the box " -Bibliothek handelt. Wenn Sie eine Anwendung für Android schreiben müssen, enthält die offizielle Website Dokumentation . Der Nachteil ist eine sehr große Menge an Code. (Nach Python ist es nur ein Schmerz.)



Also fangen wir an. Gemäß der Dokumentation zum Arbeiten mit Sitzungen können Sie CookieManager verwenden :



CookieManager cookieManager = new CookieManager(null, CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);


Mit diesem Ansatz zu beachtende Dinge:



  • "CookiePolicy.ACCEPT_ALL" gibt an, mit allen Cookies zu arbeiten.
  • Die Variable cookieManager wird nirgendwo anders verwendet. Es steuert alle Verbindungen. Wenn Sie mehrere aktive Sitzungen unterstützen müssen, müssen Sie Cookies in dieser einen Variablen mit Ihren Händen ändern


In diesem Sinne können Sie in einer Zeile schreiben:



 CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));


Absätze 1 und 2. Führen Sie die GET-Anforderung zum Empfangen des ersten Cookies aus:



URL url = new URL("http://localhost:8080/login");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
final StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
}


Danach enthält unser cookieManager das Cookie vom Server und ersetzt es bei der nächsten Anforderung automatisch.



Der Spaß beginnt mit einer POST-Anfrage.



url = new URL("http://localhost:8080/login");
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");


Sie müssen in die Überschriften "Inhaltstyp: application / x-www-form-urlencoded" schreiben.



Warum die Methode mit der Methode getHeaderField setRequestProperty und nicht setHeaders (oder addHeaders) heißt, ist ein Rätsel.



con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");


Als nächstes kommt der Code, der aus irgendeinem Grund nicht klar ist und nicht unter die Haube der Bibliothek geschoben wird.



con.setDoOutput(true);


Wir benötigen diese Codezeile, um den ausgehenden Stream zu öffnen. Es ist lustig, dass wir ohne diese Zeile die folgende Nachricht erhalten:



Ausnahme im Thread "main" java.net.ProtocolException: Kann nicht in eine URLConnection schreiben, wenn doOutput = false - setDoOutput (true) aufrufen

Wir öffnen den ausgehenden Stream und notieren dort den Login und das Passwort:



final DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes("username=Fox&password=123");
out.flush();
out.close();


Es bleibt die Antwort von der bereits weitergeleiteten Anfrage zu lesen.



Java-Implementierung, HttpURLConnection ohne CookieManager



Sie können ohne den CookieManager implementieren und die Bewegung von Cookies selbst steuern.

Punkt 1 und 2. Wir nehmen den Keks heraus.



URL url = new URL("http://localhost:8080/login");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
final StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
String cookie = con.getHeaderField("Set-Cookie").split(";")[0];
}


Als nächstes senden wir eine POST-Anfrage, nur diesmal durch Einfügen eines Cookies und Deaktivieren der automatischen Umleitung Vorher müssen Sie Zeit haben, um einen neuen Cookie herauszuholen:



//  
url = new URL("http://localhost:8080/login");
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
// headers  cookie
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("Cookie", cookie);
// 
con.setInstanceFollowRedirects(false);
//   
con.setDoOutput(true);
final DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes("username=Fox&password=123");
out.flush();
out.close();
//    cookie
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
final StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
String cookie2 = con.getHeaderField("Set-Cookie").split(";")[0];


Als nächstes fügen wir einfach allen Anfragen die folgende Zeile hinzu:



con.setRequestProperty("Cookie", cookie2);


Hoffe es war hilfreich. Die Kommentare begrüßen einfachere Optionen.



All Articles