# Login auf website per Java



## Langer (22. Aug 2016)

Hallo,
mein Problem:
Ich möchte mich gerne auf http://www.goofbid.com/ einloggen und dann ein paar Daten aus meinem Account auslesen. Langfristig möchte ich eine android app damit erstellen (nur für mich, um nicht in i-welche rechtlichen Konflikte zu geraten), die genau das tut. (Habe z.Z. einen workaround gemacht mit dem login über webView, den ich aber ersetzen möchte).

Ein viel versprechendes Tutorial habe ich auf der Seite http://www.mkyong.com/java/apache-httpclient-examples/ gefunden. Das Problem ist, dass ich nicht weiß, welche 
"post.setHeader" ich wie ändern muss, bzw bei der "// Google form id".

Ich habe den Datenverkehr schon mit Chrome erfasst (s. Bild), weiß aber nach wie vor nicht, was ich wie ändern muss.
Wenn jemand den Code von oben anpassen könnte wäre das grandios. Aber über Tipps und Tutorials wäre ich natürlich auch schon dankbar. 

Viele Grüße


----------



## Langer (22. Aug 2016)

Ich habe mal den Code abgeändert. Leider ohne Erfolg. Ich lande wieder auf der Login Seite...

```
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class LoginGoofbid {

  private List<String> cookies;
  private HttpsURLConnection conn;

  private final String USER_AGENT = "Mozilla/5.0";

  public static void main(String[] args) throws Exception {

    String url = "https://www.goofbid.com/auth";
    String sniper = "https://www.goofbid.com/account/sniper";

    LoginGoofbid http = new LoginGoofbid();

    // make sure cookies is turn on
    CookieHandler.setDefault(new CookieManager());

    // 1. Send a "GET" request, so that you can extract the form's data.
    String page = http.GetPageContent(url);
    String postParams = http.getFormParams(page);
   

    // 2. Construct above post's content and then send a POST request for
    // authentication
    http.sendPost(url, postParams);

    // 3. success then go to gmail.
    String result = http.GetPageContent(sniper);
    System.out.println(result);
  }
 
  private String GetPageContent(String url) throws Exception {

    URL obj = new URL(url);
    conn = (HttpsURLConnection) obj.openConnection();

    // default is GET
    conn.setRequestMethod("GET");

    conn.setUseCaches(false);

    // act like a browser
    conn.setRequestProperty("User-Agent", USER_AGENT);
    conn.setRequestProperty("Accept",
        "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
    conn.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
    if (cookies != null) {
        for (String cookie : this.cookies) {
            conn.addRequestProperty("Cookie", cookie.split(";", 1)[0]);
        }
    }
    int responseCode = conn.getResponseCode();
    System.out.println("\nSending 'GET' request to URL : " + url);
    System.out.println("Response Code : " + responseCode);

    BufferedReader in =
            new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
    }
    in.close();

    // Get the response cookies
    setCookies(conn.getHeaderFields().get("Set-Cookie"));

    return response.toString();

  }

  private void sendPost(String url, String postParams) throws Exception {

    URL obj = new URL(url);
    conn = (HttpsURLConnection) obj.openConnection();

    // Acts like a browser
    conn.setUseCaches(false);
    conn.setRequestMethod("POST");
    conn.setRequestProperty("Host", "www.goofbid.com:443");
    conn.setRequestProperty("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
    conn.setRequestProperty("Accept-Encoding","gzip, deflate, br");
    conn.setRequestProperty("Accept-Language", "de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,es;q=0.2");
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    for (String cookie : this.cookies) {
        conn.addRequestProperty("Cookie", cookie.split(";", 1)[0]);
    }
    conn.setRequestProperty("Origin", "http://www.goofbid.com");
    conn.setRequestProperty("Referer", "http://www.goofbid.com/");
    conn.setRequestProperty("Upgrade-Insecure-Requests", "1");
    conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36");
   
   
    conn.setDoOutput(true);
    conn.setDoInput(true);

    // Send post request
    DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
    wr.writeBytes(postParams);
    wr.flush();
    wr.close();

    int responseCode = conn.getResponseCode();
    System.out.println("\nSending 'POST' request to URL : " + url);
    System.out.println("Post parameters : " + postParams);
    System.out.println("Response Code : " + responseCode);

    BufferedReader in =
             new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
    }
    in.close();
   
  }



  public String getFormParams(String html)
        throws UnsupportedEncodingException {

    System.out.println("Extracting form's data...");


    List<String> paramList = new ArrayList<String>();

        paramList.add("referer" + "=" + URLEncoder.encode("?", "UTF-8"));
        paramList.add("username" + "=" + URLEncoder.encode("MEIN USERNAME", "UTF-8"));
        paramList.add("password" + "=" + URLEncoder.encode("MEIN PW", "UTF-8"));



    // build parameters list
    StringBuilder result = new StringBuilder();
    for (String param : paramList) {
        if (result.length() == 0) {
            result.append(param);
        } else {
            result.append("&" + param);
        }
    }
    return result.toString();
  }

  public List<String> getCookies() {
    return cookies;
  }

  public void setCookies(List<String> cookies) {
    this.cookies = cookies;
  }

}
```


----------



## KaffeeFan (23. Aug 2016)

Ich würde das ganze mit Selenium realisieren. Finde ich um einiges einfacher...

Gruß
Luk


----------



## mrBrown (23. Aug 2016)

Welchen Statuscode und welche Header bekommst du denn zurück?


----------



## Langer (23. Aug 2016)

KaffeeFan hat gesagt.:


> Ich würde das ganze mit Selenium realisieren. Finde ich um einiges einfacher...


Das werde ich vsl als nächstes probieren.



mrBrown hat gesagt.:


> Welchen Statuscode und welche Header bekommst du denn zurück?



Als "Response Code" sagt mir die Console immer 200. Wie ich die Header auslese weiß ich nicht (wie geht das?). Als "response" bekomme ich die Login-Seite zurück.


----------



## stg (23. Aug 2016)

Im FireFox sieht das z.B. so aus:
 

Ich vermute dein Problem liegt darin, dass du keine gültige "Session-ID" (wie sie dort heißt, hab ich nicht geschaut, mitunter sind es auch mehrere...)  mitsendest. Vergleiche hier zu mal wirklich exakt, was beim Login als Anfrage an den Server gesendet wird, wenn du dich manuell über die Seite anmeldest, mit dem, was du generierst. 

Selenium ist mMn übrigens nicht das Mittel der Wahl. Du willst ja gerade von so einer schwergewichtigen Lösung weg...


----------



## KaffeeFan (24. Aug 2016)

stg hat gesagt.:


> Selenium ist mMn übrigens nicht das Mittel der Wahl. Du willst ja gerade von so einer schwergewichtigen Lösung weg...



Warum schwergewichtig? Also der Code für den Login wären etwa 50 Zeilen code mit Selenium...


----------



## stg (24. Aug 2016)

Das ist nicht gemeint. Er will ja eine Handy-App entwickeln, da sollte die Anwendung möglichst Resourcen-schonend sein. Mit Selenium bläst du deine App aber direkt mal um knapp 10MB auf und sorgst dafür, dass sie unverhältnismäßg viel RAM frisst. Dafür, dass du eigentlich nur ein paar wenige HTTP requests rausschicken willst, ist's das eigentlich nicht wert. Außerdem weist du ja gar nicht, welchen Browser der User auf seinem Gerät hat, da lauert also direkt der erste große Stolperstein. Mit Selenium machst du ja im Grunde nichts weiter, als einen Browser fernzusteuern. Selenium ist eher für umfangreichere voll-automatisierte Tests der UI einer Anwendung ausgelegt.
Außerdem sagt ja schon der Name, dass es schwergewichtig ist, Selen is ja ein Schwermetall


----------



## thecain (24. Aug 2016)

Selenium ist ja auch ein Testframework. Ich verstehe nicht ganz warum das in letzter Zeit in production code verwendet wird.


----------



## Langer (24. Aug 2016)

stg hat gesagt.:


> Vergleiche hier zu mal wirklich exakt, was beim Login als Anfrage an den Server gesendet wird, wenn du dich manuell über die Seite anmeldest, mit dem, was du generierst.


Im Anhang ist ein Screenshot aus Chrome. An dem habe ich mich orientiert, aber komme nach wie vor nicht auf die Seite.
Wie kann ich mir denn auf die Console ausgeben lassen, was ich per java sende? Damit ich es vergleichen kann?
Zu Selenium: Ich wollte es eigtl per post und get machen. Es ist aber evtl eine Alternative, die ich allerdings wie stq sagt vermeiden wollte.


----------



## Langer (3. Sep 2016)

Ich habe nun Fiddler entdeckt und versuche nun damit die Kommunikation von java mit chrome zu vergleichen...
hilfreicher Link: https://blog.davidwesst.com/2015/10/Capturing-HTTPS-Traffic-in-Java-with-Eclipse-and-Fiddler/


----------



## mrBrown (3. Sep 2016)

Was mir grad auffälllt, der Request im Browser enthält ein `submit: Login`, dein Request mit Java nicht.


----------



## Langer (6. Sep 2016)

mrBrown hat gesagt.:


> Was mir grad auffälllt, der Request im Browser enthält ein `submit: Login`, dein Request mit Java nicht.


Genau das habe ich mit Fiddler jetzt auch rausbekommen. Jetzt habe ich allerdings ein weiteres Problem:
Vergleich der Post methoden:
===============================

"****"dienen der Anonymisierung ...
_*Java:*
POST https://www.goofbid.com/auth/post_login HTTP/1.1
Host: www.goofbid.com
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,es;q=0.2
Content-Type: application/x-www-form-urlencoded
Referer: https://www.goofbid.com/auth/login?referer=?
Origin: https://www.goofbid.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Connection: keep-alive
Content-Length: 60
Cookie: __cfduid=d7c901152ca*******************************473146483;  
goofbaysession=p2721g96sgd**************cp7; user_id=841**10c-7**2-1**6-bb97-0***********7;

referer=%3F&username=MEINUSERNAME&password=MEINPW&submit=Login

*Chrome:*
POST https://www.goofbid.com/auth/post_login HTTP/1.1
Host: www.goofbid.com
Connection: keep-alive
Content-Length: 60
Cache-Control: max-age=0
Origin: https://www.goofbid.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: https://www.goofbid.com/auth/login?referer=?
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,es;q=0.2
Cookie: __cfduid=dd1094557a49dff7b3a75*************73146998; user_id=b7****6c-7**3-11e6-b***-06b4f****bff; goofbaysession=943*****c2271f9********ba2a60dcf224248ca9fc%7E696c2bnv4id********8f1k82

referer=%3F&username=MEINUSERNAME&password=MEINPW&submit=Login
===============================

_
Wenn ich mir dann die cookies ausgeben lasse in der "Post" Methode:
   for (String cookie : this.cookies) {
        conn.addRequestProperty("Cookie", cookie);
       System.out.println(cookie);
   }
finde ich nur:
_goofbaysession=5a75e42f8a06f74a6************0e61bfe49e%7Ep2721g96sgds4arl4061of5cp7; expires=Tue, 06-Sep-2016 09:21:23 GMT; Max-Age=7200; path=/
goofbaysession=p2721g96sgd*****061of5cp7; expires=Tue, 06-Sep-2016 09:21:23 GMT; Max-Age=7200; path=/_

Mein Fragen:
1) Warum bekomme ich bei dem _System.out.println(cookie); _nicht die ___cfduid _und_ user_id _ausgegeben?
2) Warum gibt es zwei _goofbaysession _cookies?
3) Warum sendet er nur den kurzen _goofbaysession _cookie?
3.1) Wie sage ich ihm, dass er den langen senden soll?


----------



## Langer (12. Sep 2016)

Ich habe es endlich geschafft...

Hier ein paar Tipps:
- Fiddler ist das Tool der Wahl: https://blog.davidwesst.com/2015/10/Capturing-HTTPS-Traffic-in-Java-with-Eclipse-and-Fiddler/

- Ich wurde mehrfach "redirected" was ich mit HttpsURLConnection.setFollowRedirects(false); verhindern konnte, sodass ich mehr Kontrolle über die cookies habe.

-Wichtig war es auch die cookies richtig zu zerlegen und nur die entsprechenden zu senden ( dabei hilft Fiddler sehr)


Damit musste ich nur noch die Ausgaben von Chrome mit von Java vergleichen und fertig.
Jetzt bin ich damit in der Lage die gewünschten Daten von der Seite zu erlangen.

Da die Seite scheinbar bald eine eigene App herausbringen möchte will ich dem nicht entgegenwirken und den fertigen Code veröffentlichen. Wenn jemand ernstes Interesse an dem Code hat, dann bitte einfach per PN melden.


----------

