# Quelltext Webseite schlägt noch immer fehl



## cheat.008 (14. Jun 2018)

Folgender Code verweigert mir bei einer bestimmten Webseite noch immer das Holen des Quelltextes. 
Wie kann ich weiter dahinter kommen als den HTTP Fehler 403 woran das liegen kann? 
Noch jemand Vorschläge für die Fehlersuche?


```
public class QuelltextReader
{
   public static void main(String[] args) throws Exception
   {
       URL url = new URL("meineWebseite");
       URLConnection connection = url.openConnection();
       connection.addRequestProperty("User-Agent",   "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0");
       connection.connect();
       BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

       String input;
       while ((input = in.readLine()) != null)
           System.out.println(input);
       in.close();
   }
}
```


```
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 403 for URL: www.meineWebseite.de
   at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
   at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
   at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
   at privat.HeaderReader.main(QuelltextReader.java:16)
```


----------



## truesoul (14. Jun 2018)

Hallo.

Darf man erfahren warum du von deiner Seite den Quelltext auslesen willst?

Ansonsten siehe Status Codes

https://de.m.wikipedia.org/wiki/HTTP-Statuscode

Grüße


----------



## Robat (14. Jun 2018)

403 steht idR für "Fehlende Zugriffsberechtigung". Um was für eine URL handelt es sich denn?


----------



## cheat.008 (14. Jun 2018)

truesoul hat gesagt.:


> Hallo.
> 
> Darf man erfahren warum du von deiner Seite den Quelltext auslesen willst?
> 
> ...



Danke, das ist mir bereits bekannt (s. Fragestellung)


----------



## cheat.008 (14. Jun 2018)

Robat hat gesagt.:


> 403 steht idR für "Fehlende Zugriffsberechtigung". Um was für eine URL handelt es sich denn?



Es ist nicht "www.meinewebsite.de". Es ist einfach eine https Website. 

Die Frage ist, gibt es eine Möglichkeit näheres rauszufinden zu dem Grund, warum der Webserver die Anfrage ablehnt (aufgrund fehlender Berechtigung ist ja sehr "breit").


----------



## truesoul (14. Jun 2018)

Und wenn es dir bekannt ist, wo ist das Problem? Siehe



Robat hat gesagt.:


> 403 steht idR für "Fehlende Zugriffsberechtigung". Um was für eine URL handelt es sich denn?


----------



## cheat.008 (14. Jun 2018)

cheat.008 hat gesagt.:


> Es ist nicht "www.meinewebsite.de". Es ist einfach eine https Website.
> 
> Die Frage ist, gibt es eine Möglichkeit näheres rauszufinden zu dem Grund, warum der Webserver die Anfrage ablehnt (aufgrund fehlender Berechtigung ist ja sehr "breit").


----------



## truesoul (14. Jun 2018)

cheat.008 hat gesagt.:


> Es ist nicht "www.meinewebsite.de". Es ist einfach eine https Website.
> 
> Die Frage ist, gibt es eine Möglichkeit näheres rauszufinden zu dem Grund, warum der Webserver die Anfrage ablehnt (aufgrund fehlender Berechtigung ist ja sehr "breit").



Diese Information wäre anfangs vielleicht auch ganz gut gewesen 

Ist ein Login notwendig? Oder greifst du evtl. nur auf der Landingpage zu?

Mehr Infos wären gut


----------



## Robat (14. Jun 2018)

Hast du denn über einen Browser Zugriff auf die Website?


----------



## cheat.008 (14. Jun 2018)

Sorry. Ja Login ist tatsächlich notwendig. Gute Idee! 
Weißt du wie man sich einloggen kann mit Java?


----------



## cheat.008 (14. Jun 2018)

Robat hat gesagt.:


> Hast du denn über einen Browser Zugriff auf die Website?


Ja über den Browser logge ich mich ein und kopiere diesen Link dann in mein Javaprogramm. 

Wie Robat aber schon richtig hingewiesen hat, müsste ich dennoch wohl den Login implementieren. 
Wisst ihr wie man das programmiert?


----------



## Robat (14. Jun 2018)

Vielleicht klappt es ja über den Authenticator. 

```
Authenticator.setDefault (new Authenticator() {
   protected PasswordAuthentication getPasswordAuthentication() {
       return new PasswordAuthentication ("username", "password".toCharArray());
   }
});
```


----------



## truesoul (14. Jun 2018)

Ja.
Aber ich kann dir übers Handy kein Code schicken. Jetzt weißt du schon wo das Problem ist. Vielleicht weiß Google wie es geht


----------



## cheat.008 (14. Jun 2018)

Robat hat gesagt.:


> Vielleicht klappt es ja über den Authenticator.
> 
> ```
> Authenticator.setDefault (new Authenticator() {
> ...



Leider nein. Selbige Exceptionausgabe.
Werde mal in die Richtung Login recherchieren. Dürft mir aber gerne noch Tipps geben ;-)


----------



## mrBrown (15. Jun 2018)

Ziemlich sicher dürfte das ein Login sein, der die Session in'nem Cookie speichert.
Du müsstest sowohl den Login (also Request mit Name, Passwort etc) als auch die entsprechende Behandlung von Cookies abbilden.


----------



## cheat.008 (15. Jun 2018)

Danke für den Tipp. Und weißt du zufällig wie man sowas angeht?


----------



## mihe7 (16. Jun 2018)

Der Web-Entwickler hat verschiedene Möglichkeiten, Login und Session zu realisieren. Klassisch wären Session-Cookie und ein HTML-Formular, mit dem Benutzername und Passwort via POST-Request an den Server gesendet werden.

Für die Cookies:
https://docs.oracle.com/javase/8/docs/api/java/net/CookieHandler.html
https://docs.oracle.com/javase/8/docs/api/java/net/CookieManager.html

Vor den Requests sollte also folgendes genügen:

```
CookieHandler.setDefault(new CookieManager());
```

Für den Login sendest Du, wenn wir von einem HTML-Formular ausgehen, einfach einen POST-Request, wobei die Formularfelder URL-kodiert (Content-Type "application/x-www-form-urlencoded") übermittelt werden. Stichworte sind HttpURLConnection und URLEncoder. Das sollte jetzt nicht allzu schwierig sein.


----------



## cheat.008 (16. Jun 2018)

Ok danke für den Ansatz.
Das sind einige neue Dinge für mich, die ich die Tage mal recherchieren und testen werde.

Also den Login als Fehlerquelle kann ich derzeit ausschließen, da selbst das holen von Daten vor dem Login mit genanntem 403 Fehler fehlschlägt. Daher werde ich bei zukünftigen Verbindungsversuchen zunächst eine Seite vor dem Login zu holen versuchen.


Ich melde mich wieder wenn es Neuigkeiten oder Probleme gibt.


----------



## cheat.008 (16. Jun 2018)

cheat.008 hat gesagt.:


> Also den Login als Fehlerquelle kann ich derzeit ausschließen, da selbst das holen von Daten vor dem Login mit genanntem 403 Fehler fehlschlägt. Daher werde ich bei zukünftigen Verbindungsversuchen zunächst eine Seite vor dem Login zu holen versuchen.



Natürlich Quatsch, sorry.
*Das Holen der Quelltextdaten VOR dem Login funktioniert.*


Habe nun zum Thema POST Request in der Insel nachgelesen:
http://openbook.rheinwerk-verlag.de...21_004.htm#mj09ddf4c4d29f03c1fa3ffe5344c0875d

Der Code sieht nun folgendermaßen aus.
Ergebnis noch immer der gleiche 403 Fehler. Scheint also noch immer
am Login zu scheitern.


```
...
   public static void main(String[] args) throws Exception
   {
       String body = "param1=" + URLEncoder.encode("<username>", "UTF-8") + "&" + "param2="
               + URLEncoder.encode("<passwort>", "UTF-8");

       CookieHandler.setDefault(new CookieManager());
       URL url = new URL("<website>");
       HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

       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.addRequestProperty("User-Agent",
               "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0");
       connection.connect();

       BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

       String input;
       while ((input = in.readLine()) != null)
           System.out.println(input);
       in.close();
   }
}
```


----------



## mihe7 (16. Jun 2018)

1. Heißen die Form-Elemente auf der Webseite wirklich param1 und param2?
2. Du musst den body schon über den OutputStream der connection rausschreiben.


----------



## mihe7 (16. Jun 2018)

Nehmen wir mal an, wir fänden unter www.meinewebseite.de/login.*html* folgenden Code


```
<form method="POST" action="login.php">
  <input type="text" name="benutzer" />
  <input type="password" name="vorbeiwort" />
  <button type="submit">OK</button>
</form>
```

Dann würde beim Klick auf den Button ein POST-Request www.meinewebseite.de/login.*php* ausgeführt. Der Body wäre dann "benutzer=xxx&vorbeiwort=xxx".


----------



## cheat.008 (16. Jun 2018)

mihe7 hat gesagt.:


> 1. Heißen die Form-Elemente auf der Webseite wirklich param1 und param2?
> 2. Du musst den body schon über den OutputStream der connection rausschreiben.




Ah, vergessen. Nein die Namen sind "login" und "password".
Danke!
Leider kenne ich mich mit HTML/PHP nicht sonderlich gut aus.


```
public class QuelltextReader
{
   public static void main(String[] args) throws Exception
   {
       String body = "login=" + URLEncoder.encode("<meinUN>", "UTF-8") + "&" + "password="
               + URLEncoder.encode("<meinPW>", "UTF-8");

       CookieHandler.setDefault(new CookieManager());
       URL url = new URL("<website>");
       HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
       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.addRequestProperty("User-Agent",
               "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0");
       connection.connect();

       OutputStreamWriter osw = new OutputStreamWriter( connection.getOutputStream() );
       osw.write(body);
       osw.flush();
     
       BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

       String input;
       while ((input = in.readLine()) != null)
           System.out.println(input);
       in.close();
   }
}
```


----------



## cheat.008 (16. Jun 2018)

mihe7 hat gesagt.:


> Nehmen wir mal an, wir fänden unter www.meinewebseite.de/login.*html* folgenden Code
> 
> 
> ```
> ...



Durch den OutputStream sende ich im "body" die Logininformationen.
Impliziert das dann sozusagen das "Betätigen" des Buttons?


----------



## mihe7 (16. Jun 2018)

Wenn Du das HTML von vorhin nimmst, dann sendet der Browser beim Betätigen des Buttons eben einen solchen Request.

Funktioniert es jetzt? Wenn nicht, wie sieht die Antwort bzw. wie sehen die Response-Header aus?


----------



## cheat.008 (16. Jun 2018)

mihe7 hat gesagt.:


> Wenn Du das HTML von vorhin nimmst, dann sendet der Browser beim Betätigen des Buttons eben einen solchen Request.



Also es gibt ja tatsächlich auf der Seite einen Anmelde-Button.
Verstehe ich das richtig, dass ich durch den "body"-String bzw. POST-Request
aktuell nur die Felder "login" und "password" fülle, aber das Betätigen des genannten Buttons noch fehlt?
Falls ja, müsste ich das ja noch in meinen Code implementieren...

Der Button:

```
<input class="button primary" value="Anmelden" data-loginphrase="Anmelden" data-signupphrase="Registrieren" tabindex="4" type="submit">
```



mihe7 hat gesagt.:


> Funktioniert es jetzt? Wenn nicht, wie sieht die Antwort bzw. wie sehen die Response-Header aus?



Leider nein.
Kannst du damit etwas anfangen?


```
Printing Response Header...

Key : Transfer-Encoding ,Value : [chunked]
Key : null ,Value : [HTTP/1.1 403 Forbidden]
Key : CF-RAY ,Value : [42bcb0a3be939720-FRA]
Key : Server ,Value : [cloudflare]
Key : Connection ,Value : [keep-alive]
Key : Last-Modified ,Value : [Sat, 16 Jun 2018 10:45:59 GMT]
Key : Date ,Value : [Sat, 16 Jun 2018 10:45:59 GMT]
Key : X-Frame-Options ,Value : [SAMEORIGIN]
Key : X-Xss-Protection ,Value : [1]
Key : Vary ,Value : [Accept-Encoding]
Key : Set-Cookie ,Value : [, ]
Key : Expires ,Value : [Thu, 19 Nov 1981 08:52:00 GMT]
Key : Expect-CT ,Value : [max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"]
Key : Cache-control ,Value : [private, max-age=0]
Key : Content-Type ,Value : [text/html; charset=UTF-8]
```


----------



## mihe7 (16. Jun 2018)

1. Du sendest den Request schon gegen die URL, die sich aus dem action-Attribut der Form ergibt?
2. Falls ja: es kann auch sein, dass die Seite die Anmeldung via JavaScript realisiert und es z. B. gar keine serverseitigen Sessions gibt (dann existiert die Session nur auf dem Client und die Authorisierung erfolgt durch ein Token, z. B. via JWT)
3. Ohne Infos zur Seite ist das ein reines Rätselraten


----------



## cheat.008 (16. Jun 2018)

mihe7 hat gesagt.:


> 1. Du sendest den Request schon gegen die URL, die sich aus dem action-Attribut der Form ergibt?



Ja



mihe7 hat gesagt.:


> 2. Falls ja: es kann auch sein, dass die Seite die Anmeldung via JavaScript realisiert und es z. B. gar keine serverseitigen Sessions gibt (dann existiert die Session nur auf dem Client und die Authorisierung erfolgt durch ein Token, z. B. via JWT)
> 3. Ohne Infos zur Seite ist das ein reines Rätselraten



Ja du hast schon recht, hatte mir das alles einfacher vorgestellt und für weiteres reichen meine HTML Kenntnisse leider nicht aus, daher werde ich mir was anderes überlegen müssen. 
Danke für deine Hilfe bis hierher!


----------



## mihe7 (16. Jun 2018)

Das ist alles kein Hexenwerk, Du musst dir einfach ansehen, wie der Login realisiert wurde. 

Du kannst z. B. in Firefox mit der "Netzwerkanalyse" (Strg+Shift+Q bzw. Strg+Shift+E oder Menü -> Web-Entwickler -> Netzwerkanalyse) die Requests genau nachvollziehen. Gleiches funktioniert in Chrome (Strg+Shift+J, Network-Tab). 

Du kannst im Browser auch mal testen, ob der Login ohne JavaScript funktioniert (Seite aufrufen, JavaScript deaktivieren, anmelden). Wenn ja, ist der bisherige Ansatz schon der richtige.


----------



## Ice-Tea (23. Dez 2018)

Für eine httpS Verbindung solltest du auch entsprechende nutzen.

https://alvinalexander.com/blog/post/java/simple-https-example

Beim Login wird es komplizierter. Du musst die Attribute-Namen der Seite übernehmen und entsprechende Werte übergeben.


----------



## mrBrown (23. Dez 2018)

Ice-Tea hat gesagt.:


> Für eine httpS Verbindung solltest du auch entsprechende nutzen.


Entsprechende "was" nutzen?

HttpsURLConnection nutzt er schon, muss man aber nicht mal explizit machen, wenn man mit URL arbeitet, wird das intern schon passend behandelt.


----------



## mihe7 (23. Dez 2018)

Abgesehen davon: nach einem halben Jahr wird er den Login hinbekommen haben.


----------

