# Mit der URL Klasse einloggen...



## PeterVonHinten (16. Dez 2012)

Ich versuche derzeit mit der URL Klasse mich auf einer Seite einzuloggen. Bei der Seite handelt es sich um paket.de, ich möchte für mich privat ein kleines Programm schreiben, sodass ich meine Bestellungen einsehen und auflisten kann, ohne das ich mich jedes mal mit dem Browser einloggen muss. Ich habe schon Probleme beim einloggen, egal ob mit Java oder mit dem Firefox Add-on Live HTTP-Headers. Ich habe mich an dieses Beispiel gehalten.

*Zur Übersichtlichkeit teile ich diesen Thread in zwei Abschnitten auf...

Live HTTP-Headers Versuch
Java-Code
*

*1. Live HTTP-Headers Versuch*
Der Seiten aufruf bei paket.de sieht wie folgt aus:

```
https://www.paket.de/pkp/appmanager/pkp/desktop?_nfpb=true&_portlet.async=false&_pageLabel=pkp_portal_page_introduction

GET /pkp/appmanager/pkp/desktop?_nfpb=true&_portlet.async=false&_pageLabel=pkp_portal_page_introduction HTTP/1.1
Host: www.paket.de
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cache-Control: max-age=0
```
Antwort vom Server auf diesem HTTP-Request:

```
HTTP/1.1 200 OK
Date: Sun, 16 Dec 2012 18:51:19 GMT
Server: DHL
X-Frame-Options: SAMEORIGIN
Cache-Control: no-cache, must-revalidate, no-store
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: PKPSESSIONID=k086QTYHv38Kyq2gCtDn4tcvV3rmQpT2THmZ9Ptc8JxCvLrvlkLp!787135418; path=/pkp; HttpOnly
X-Content-Type-Options: nosniff
ntCoent-Length: 52940
Keep-Alive: timeout=25
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
Content-Encoding: gzip
Content-Length: 10094
```


Jetzt nehme ich mir den Cookie aus dem Antwort header und sende diesen mit den Login-Daten über einen neuen Post Request ab:

```
https://www.paket.de/pkp/appmanager/pkp/desktop?_nfpb=true&_nfls=false&_pageLabel=pkp_portal_page_login&_windowLabel=portletInstance_customerLogin&portletInstance_customerLogin_actionOverride=/de/deutschepost/ubbrief/dhl/pkp/portlets/externallogin/externalLogin&_nfxr=true

POST /pkp/appmanager/pkp/desktop?_nfpb=true&_nfls=false&_pageLabel=pkp_portal_page_login&_windowLabel=portletInstance_customerLogin&portletInstance_customerLogin_actionOverride=/de/deutschepost/ubbrief/dhl/pkp/portlets/externallogin/externalLogin&_nfxr=true HTTP/1.1
Host: www.paket.de
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
x-bea-netuix-xhr: true
Referer: https://www.paket.de/pkp/appmanager/pkp/desktop?_nfpb=true&_portlet.async=false&_pageLabel=pkp_portal_page_introduction
Content-Length: 54
Cookie: PKPSESSIONID=k086QTYHv38Kyq2gCtDn4tcvV3rmQpT2THmZ9Ptc8JxCvLrvlkLp!787135418; s_cc=true; s_sq=%5B%5BB%5D%5D
Pragma: no-cache
Cache-Control: no-cache
	dhl_gkuser=4514235&dhl_gkpass=fasdgdasfg&headerLogin=1
```
Als Antowort auf diesen Request bekomme ich eine Datei namens "desktop" vom Typ text/x-netuix-json-comment-filtered angeboten. Also war der login nicht erolgreich.


*2. Java-Code*
Das der folgene Teil nicht funktionieren wird ist mir klar, wenn es schoh nicht mit Live HTTP-Headers funktioniert, kann es ja garnicht funktionieren. Dennoch füge ich es hinzu, vllt. findet ja auch jemand hier einen Fehler. (Nicht kompilierbar und alles zu einem Code zusammengefügt um es kurz zu halten, bestimmte Teile des Codes waren in einzelne Methoden.)

```
URL paket;
HttpsURLConnection connection;
String body, cookie, email, password;

paket = new URL("https://www.paket.de/pkp/appmanager/pkp/desktop?_nfpb=true&_nfxr=false&_pageLabel=pkp_portal_page_introduction&_nfls=false");
connection = (HttpsURLConnection) paket.openConnection();
connection.setRequestMethod("GET");
connection.connect();
cookie = connection.getHeaderField("Set-Cookie");
System.out.println(connection.getResponseCode());





paket = new URL("https://www.paket.de/pkp/appmanager/pkp/desktop?_nfpb=true&_nfls=false&_pageLabel=pkp_portal_page_login&_windowLabel=portletInstance_customerLogin&portletInstance_customerLogin_actionOverride=/de/deutschepost/ubbrief/dhl/pkp/portlets/externallogin/externalLogin&_nfxr=true");
connection = (HttpsURLConnection) paket.openConnection();
body = "dhl_gkuser=" + URLEncoder.encode(email, "UTF-8") + "&" + "dhl_gkpass=" + URLEncoder.encode(password, "UTF-8") + "&" + "headerLogin=1";

connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", String.valueOf(body.length()));
connection.setRequestProperty("Cookie", cookie);

OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(this.body);
writer.flush();

BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
for(String line; (line = reader.readLine()) != null;)
{
	data.append(line);
}

writer.close();
reader.close();
```


Vielleicht kann mir ja jemand helfen.
Liebe Grüße,
Peter


----------



## Bizarrus (16. Dez 2012)

Das mit dem Fetchen ist dort so eine Sache.
Hab mich auch gerade mal kurz drangesetzt, weiter bin ich nach dem Login aber nicht gekommen.

Wichtig ist, das der Spezielle Ajax-Header *x-bea-netuix-xhr: true* gesetzt ist, da vieles dort per Ajax nachgeladen wird und ein JSON-String zurückgegeben wird.

Hier mal meine Klassen:

```
public class Start {
	public static void main(String[] args) {
		Paket instance = new Paket();
		instance.login("BENUTZERNAME", "PASSWORT");
	}
}
```


```
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Paket {
	protected static String cookie			= null;
	protected static Vector<String> pakete	= null;
	
	public void login(String username, String password) {
		pakete		= new Vector<String>();
		String data = request("https://www.paket.de/pkp/appmanager/pkp/desktop?_nfpb=true&_nfls=false&_pageLabel=pkp_portal_page_login&_windowLabel=portletInstance_customerLogin&portletInstance_customerLogin_actionOverride=/de/deutschepost/ubbrief/dhl/pkp/portlets/externallogin/externalLogin&_nfxr=true", "dhl_gkuser=" + username + "&dhl_gkpass=" + password + "&headerLogin=1");
	
		if(data.indexOf("Ihre Eingabe war leider nicht erfolgreich") > 0) {
			System.err.println("Login Fehlgeschlagen!");
		} else {
			System.out.println("Login OK");
			cookie = null;
			request("https://www.paket.de:443/pkp/appmanager/pkp/desktop?_nfpb=true&_portlet.async=false&_pageLabel=pkp_portal_page_introduction&startMenu=true&_nfls=false", null);
			getPakete();
		}
	}
	
	public void getPakete() {
		// Pakete auslesen
		String data	= request("https://www.paket.de/pkp/appmanager/pkp/desktop?_nfpb=true&_windowLabel=T7200333531331734869007&T7200333531331734869007_actionOverride=%2Fde%2Fdeutschepost%2Fubbrief%2Fdhl%2Fpkp%2Fportlets%2Fmyshipments%2FshowCurrentShippings&_nfxr=true", null);
		Pattern p	= Pattern.compile("(?:idc=)([\\w-]+)&extendedSearch");
		Matcher m	= p.matcher(data);
		System.out.println(data);
		int i		= 0;
		
		while(m.find()) {
			System.out.println(m.group());
			i++;
		}
		
		if(i == 0) {
			System.err.println("Keine Pakete gefunden");
		}
	}
	
	public String request(String url, String data) {
		try {
			URL request						= new URL(url);
			HttpURLConnection connection	= (HttpURLConnection) request.openConnection();  
			
			connection.setDoOutput(true);
			
			if(data != null) {
				connection.setDoInput(true);
			}
			
			connection.setInstanceFollowRedirects(false); 
			
			if(data != null) {
				connection.setRequestMethod("POST"); 
			}
			
			connection.setRequestProperty("Content-Type",		"application/x-www-form-urlencoded"); 
			connection.setRequestProperty("charset",			"utf-8");
			
			if(data != null) {
				connection.setRequestProperty("Content-Length",		"" + Integer.toString(data.getBytes().length));
			}
			
			connection.setRequestProperty("Referer",			"https://www.paket.de/pkp/appmanager/pkp/desktop");
			connection.setRequestProperty("x-bea-netuix-xhr",	"true");
			connection.setRequestProperty("User-Agent",			"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11");
		
			if(cookie != null) {
				connection.setRequestProperty("Set-Cookie",			cookie); 
			}
			
			connection.setUseCaches(false);
			
			DataOutputStream wr;
			
			if(data != null) {
				wr	= new DataOutputStream(connection.getOutputStream());
				wr.writeBytes(data);
				wr.flush();
				wr.close();
			}
			
			String line;
			StringBuffer output		= new StringBuffer();
			BufferedReader reader	= new BufferedReader(new InputStreamReader(connection.getInputStream()));

			while((line = reader.readLine()) != null) {
			   output.append(line);
			   System.err.println(line);
			}
			
			if(cookie == null) {
				cookie				= connection.getHeaderField("Set-Cookie");
				System.out.println(cookie);
			}
			
			reader.close();     
			connection.disconnect();
			
			return output.toString();
		} catch(IOException e) {
			e.printStackTrace();
		}
		
		return "";
	}
}
```

Meiner Meinung nach, wird bei mir die Session nicht korrekt gesetzt, kann aber höchstwahrscheinlich auch an SSL liegen, warum des so Problemchen bereitet...

Unter den JSON-Eintrag "markup" sollte nämlich normalerweise die Paket-Links zu finden sein, die man dann einfach Matcht.


----------



## tröööt (17. Dez 2012)

naja freunde ... das problem dürfte einfach die arbeitsweise der page sein ...

wenn die seite halt viel mit AJAX und JSON arbeitet dann wird in java wohl einfach URL.openConnection() nicht ausreichen ...

hierfür bräuchte man schon gute libs ala HTMLunit oder Apache-Commons oder was weis ich was es noch gibt ...

fakt ist halt : es werden keine kompletten seiten übertragen sondern nur die nötigen informationen ... und um damit was anfangen zu können brauchts passende libs ... denn java selbst kann das von haus aus nicht ... oder man muss alles mit Sockets und RAW-Streams selbst nachprogrammieren ...


----------



## PeterVonHinten (17. Dez 2012)

Danke Bizarrus für deine Hilfe, aber ich glaube ich kann das vergessen mit der URL Klasse. Mit HTMLunit habe ich das ganze in 15 Minuten hinbekommen, einfacher gehts wohl nicht.


----------



## Bizarrus (18. Dez 2012)

tröööt, nicht unbedingt. Wenn die Anfrage genau gleich ist, auch mit gleichbleibender session, dann dürfte es auch so gehen.

Hatte mich nochmals dran gesetzt und paket.de liegen geladden, dafür aber mobil.dhl.de genommen, dort ist die page etwas vereinfacht zu handhaben.


----------



## PeterVonHinten (19. Dez 2012)

Scheint mit HTMLunit schön und einfach zu sein, aber die CPU Auslastung beträgt allein beim einloggen ca. 70%. Selbst das einloggen dauert ca. 20 Sekunden.

@Bizarrus: Denkst du das es viel einfacher geht bei der Seite von DHL für's Handy? Wenn ja, dann würde ich mich auch nochmal ransetzen.


----------



## Bizarrus (20. Dez 2012)

PeterVonHinten, ich versuche dir heute Abend, wenn ich es schaffe, die Klasse hier online zu setzen.

Generell funktioniert bei mir folgendes bereits:
- Login
- Fetch der eingetragenen Pakete

Was ich noch machen wollte:
- Paketinformationen fetchen (Lieferstatus, etc)
- Pakete hinzufügen

Wo ich beim Login aber noch die Probleme habe, ist mit der Session.
Cookies und Set-Cookies funktioniert bei mir leider noch nicht so, wie es sein sollte.

Der Ablauf wäre ja folgender:
1. Anmeldung mit benutzerdaten
2. Cookies aus dem Response zwischenspeichern
3. Paketübersichtsseite aufrufen (Request mit der zuvor zwischengespeicherten Cookies, wegen der Session-ID)

Komisch ist, dass wenn ich die Cookies hardcoded setze, dass ich dann an den Paketinfos rankomme. Im Ausgeloggtem Zustand kommt man da ja ohnehin nicht dran.

Aus dem Aufbau der Cookies werde ich ohne hin nicht ganz schlau.
Es gibt halt den Wert *FITSID*, was meiner Vermutung nach die Session-ID ist.

Dann gibt es aber wiederrum folgende Werte:


> NSC_ng-eim-n=ffffffffda4d565345525d5f4f58455e445a4a1234a3; facdd=1; facdone=true; facdl=2048#604; facdp=604#2048; facdo=landscape



Einige wären klar. *facdo *wäre die Screen Orientation (landscape oder portrait), aber was die anderen Parameter bedeuten könnten und ggf. eine Rolle bei der Authentifizierung über Cookies eine Rolle spielen, bleibt mir verborgen.

Aus einigen Werten werde ich nun schlau:
facdo (übersetzt *facd*isplay*o*rientation)
facdl (Übersetzt *facd*isplay*l*andscape, Displaygröße in Pixel bei Landscape)
facdp (Übersetzt *facd*isplay*p*ortrait, Displaygröße in Pixel bei Portrait)

Was natürlich das "fac" beduetet, kann ich nicht sagen.


----------



## PeterVonHinten (20. Dez 2012)

Danke für deine Mühe, mich interessiert es sehr wie du es nun mit den Paketen hinbekommen hast, ich habe es nämlich immer noch nicht geschafft. Ich bin sehr auf dein Ergebnis gespannt!


----------



## Bizarrus (22. Dez 2012)

Bist leider etwas in vergessenheit geraten. Liegt wohl daran, dass ich die letzen Tage bei Bekannten übernachtet hatte :-D


```
public class Start {
	public static void main(String[] args) {
		Paket instance = new Paket();
		instance.login("BENUTZERNAME", "PASSWORT");
		
		int pakete = instance.getPakete();
		System.out.println("Pakete vorhanden: " + pakete);
	}
}
```


```
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ssl.HttpsURLConnection;

public class Paket {
	protected static String cookie			= null;
	protected static Vector<String> pakete	= null;
	protected static boolean ajax			= false;
	protected static String referer			= null;
	
	public void setCookie() {
		try {
			URLConnection connection	= new URL("https://mobil.dhl.de/i/pages/login.xml").openConnection();
			handleCookies(connection);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void handleCookies(URLConnection connection) {
		List<String> cookies	= connection.getHeaderFields().get("Set-Cookie");
		if(cookie == null) {
			cookie					= "s_cc=true; s_sq=%5B%5BB%5D%5D; facdd=1; facdone=true; facdl=1920#574; facdp=574#1920; facdo=landscape";
		
			for(Iterator<String> iter = cookies.iterator(); iter.hasNext();) {
				String v	= iter.next();
				cookie = cookie + "\r\n" + v;
	        }
		}
		
		cookie = cookie.replace(" secure; httpOnly", "");
		cookie = cookie.replace("secure;httponly", "");
		System.out.println(cookie);
	}
	
	public void login(String username, String password) {
		setCookie();
		pakete		= new Vector<String>();
		referer		= "https://mobil.dhl.de/i/pages/login.xml";
		ajax		= false;
		String data = null;
		
		try {
			data = request("https://mobil.dhl.de/i/pages/login.xml", "sv-method=query&query=sv_meinpaket&query_type=login&login=" + URLEncoder.encode(username, "ISO-8859-1") + "&password=" + URLEncoder.encode(password, "ISO-8859-1") + "&stayLoggedIn=true&action=Einloggen");
			System.out.println(data);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		
		if(data == null) {
			System.err.println("Systemfehler!");
		} else if(data.indexOf("<title>Login") > 0) {
			if(data.indexOf("Fehler") > 0 || data.indexOf("darf nicht leer sein.") > 0) {
				System.err.println("Login Fehlgeschlagen!");
			} else {
				System.out.println("Login OK");
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				fetchPakete();
			}
		} else {
			System.err.println("Login Fehlgeschlagen!");
		}
	}
	
	public void fetchPakete() {
		System.out.println("Fetch");
		
		// Pakete auslesen
		ajax		= true;
		referer		= "https://mobil.dhl.de/sendung";
		String data = request("https://mobil.dhl.de/;b=qk0xGwjTi-dd0CouxNkjhA/", null);
		Pattern p	= Pattern.compile("\">([0-9]+)</a>");
		Matcher m	= p.matcher(data);
		int i		= 0;
		System.out.println(data);
		while(m.find()) {
			String id = m.group(1);
			if(!pakete.contains(id)) {
				pakete.add(id);
				System.err.println("Add " +  id);
			}
			i++;
		}
		
		if(i == 0) {
			System.err.println("Keine Pakete gefunden");
		}
	}
	
	public int getPakete() {
		return pakete.size();
	}
	
	public String request(String url, String data) {
		try {
			URL request						= new URL(url);
			HttpsURLConnection connection	= (HttpsURLConnection) request.openConnection();  
			
			connection.setDoOutput(true);
			
			if(data != null) {
				connection.setDoInput(true);
			}
			
			connection.setInstanceFollowRedirects(false); 
			
			if(data != null) {
				connection.setRequestMethod("POST");
				connection.setRequestProperty("Content-Type",		"application/x-www-form-urlencoded"); 
			} else {
				connection.setRequestMethod("GET");
			}
			
			connection.setRequestProperty("charset",				"utf-8");
			connection.setRequestProperty("Origin",					"https://mobil.dhl.de");
			
			if(data != null) {
				connection.setRequestProperty("Content-Length",		"" + Integer.toString(data.getBytes().length));
			}
			
			if(referer != null) {
				connection.setRequestProperty("Referer",			referer);
				referer = null;
			}
			
			//connection.setRequestProperty("x-bea-netuix-xhr",		"true");
			connection.setRequestProperty("User-Agent",				"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11");
			
			if(cookie.contains("\r\n")) {
				String[] c = cookie.split("\r\n");
				for(int i = 0; i < c.length; i++) {
					if(i == 0) {
						connection.setRequestProperty("Cookie",			c[i]);
					} else {
						connection.addRequestProperty("Cookie",			c[i]);
					}
				}
			} else {
				connection.setRequestProperty("Cookie",				cookie);
			}
			
			if(ajax == true) {
				connection.setRequestProperty("X-Requested-With",	"XMLHttpRequest");
				ajax = false;
			}
			
			connection.setUseCaches(false);
			DataOutputStream wr;
			
			if(data != null) {
				wr	= new DataOutputStream(connection.getOutputStream());
				wr.writeBytes(data);
				wr.flush();
				wr.close();
			}
			
			String line;
			StringBuffer output		= new StringBuffer();
			BufferedReader reader	= new BufferedReader(new InputStreamReader(connection.getInputStream()));

			while((line = reader.readLine()) != null) {
			   output.append(line + "\n");
			}
			
			reader.close();     
			connection.disconnect();
			
			handleCookies(connection);
			
			return output.toString();
		} catch(IOException e) {
			e.printStackTrace();
		}
		
		return "";
	}
}
```

Um es mit den Cookies zu testen, mach einfach folgendes:
1. Kommentier folgende Zeilen aus, wo die Cookies des Requests gespeichert werden (Zeile 189 & Zeile 26)
2. Logge dich normal über dem Browser mal auf mobil.dhl.de ein
3. Ziehe dir aus dem Response die Cookie-Werte
4. Setze die Cookie-Werte auf Zeile 19 (Variable: cookie)

Dann kannst du direkt die Pakete Fetchen..

Was mich gar verwundert ist, dass bei beiden Seiten (egal ob DHL oder paket.de) die Cookies 2x gesetzt werden. Es tauchen also im Request bzw. Response zwei mal hintereinander Cookie bzw. Set-Cookie auf. Ist das überhaupt Standardkonform? Weiß ich gerade nicht... Wenn nein, welcher Wert wird letztendlich genutzt? Der erstgesetzte oder der Letze?!


----------

