Hallo,
ich habe ein Problem:
Ich poste zu einem Embedded Webserver eine 1MB-Datei.
Dieser Webserver funktioniert schon seit einigen Jahren sehr gut und
stabil, es ist aber möglich, dass er noch ein paar Probleme hat.
Bevor man zu der Uploadseite kommt, muss man sich einloggen und bei dem
Post werden die Credentials dann mitgeschickt (digest).
Der Safari-Webbrowser macht das nicht. Er probiert immer einen Zugriff
ohne Authentifizierung und schickt sie erst nach einem 401 Error.
Genau da ist das Problem: Der Safari fängt an zu posten und nach ein
paar Kb schickt der Embedded Webserver eine 401-Meldung.
Irgendwie versteht das der Safari diese nicht und ich bin beim Suchen
woran das liegt.
(Ich würde erwarten, dass der Safari nach der 401-Botschaft den Post
wiederholt mit den Credentials im Header, so wie es bei allen anderen
geschützten Websiten auch macht)
Müsste der Embedded Webserver abwarten, bis der komplette Upload fertig
ist, bevor er die 401-Meldung schickt?
Muss der Webserver das PSH-, FIN- oder RST-Flag setzen, wenn er schon
den POST des Client abbricht?
Bei Wireshark/Analyze/Follow TCP Stream sieht das so aus: 1 | POST update.html HTTP/1.1
| 2 | Host: 192.168.1.1
| 3 | Origin: http://192.168.1.1
| 4 | Content-Length: 800723
| 5 | User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) Version/5.0.6 Safari/533.22.3
| 6 | Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryFOqmS9nBVqEBbKLF
| 7 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
| 8 | Referer: http://192.168.1.1/update.html
| 9 | Accept-Language: de-de
| 10 | Accept-Encoding: gzip, deflate
| 11 | Connection: keep-alive
| 12 |
| 13 | ------WebKitFormBoundaryFOqmS9nBVqEBbKLF
| 14 | Content-Disposition: form-data; name="dateiupdate"; filename="file.gz"
| 15 | Content-Type: application/x-gzip
| 16 |
| 17 | ....B..L..yyyzzz.elf.S19..}Y..*.....{a.>.....^.......y3.....0f.B.B.......w...
| 18 | .....~kiHTTP/1.0 401 Unauthorized
| 19 | Server: embeddedServer
| 20 | Connection: close
| 21 | Content-Type: text/html
| 22 | WWW-Authenticate: Digest realm="xxxxx", nonce=xxxx, qop="xxxx"
| 23 |
| 24 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html><head>
| 25 | <meta name="generator" content="HTML Tidy for Windows (vers 1st April 2002), see www.w3.org">
| 26 | <title>401 Unauthorized</title></head><body>
|
Das erste Paket zu der 401-Botschaft hat FIN gesetzt, vorher wurden ganz
normal die Pakete des Client mit ACKs bestätigt.
1 | Header length: 20 bytes
| 2 | Flags: 0x11 (FIN, ACK)
|
Also du wirfst hier einiges durcheinander. HTTP spielt sich oberhalb von
TCP ab.
Zum POST request gehören natürlich auch die Daten dazu, die kannst du
natürlich ignorieren aber nicht mittendrin die (TCP) Verbindung canceln.
Wie sich einzelne Operationen verhalten sollen steht in der zugehörigen
RFC für HTTP (http://tools.ietf.org/html/rfc2616), das alles darf aber
keinesfalls Auswirkungen auf die Transportschicht (TCP/IP) haben!
Jürgen G. schrieb:
> Müsste der Embedded Webserver abwarten, bis der komplette Upload fertig
> ist, bevor er die 401-Meldung schickt?
Die Antwort darf er vorher senden, nur lesen sollte er den Request auf
jedenfall zu ende!
> Connection: close
ist bei HTTP 1.0 nicht definiert wenn ich mich recht erinnere. Auch
müßte man mal schauen ob ein HTTP 1.0 Server bei einer HTTP 1.1
Anfrage nicht mit dem Status "505 HTTP Version Not Supported" antworten
sollte. (edit: Das ist so okay, der Client sagt nur die höchste Version
welche er versteht, der Server darf "downgraden")
Mal interessehalber: Warum forderst du nicht schon beim GET eine
Autorisation?
Dafür gabs doch eigentlich die "Expect: 100-continue" header, mit der
der Browser mitteilt dass er erst wissen will ob der Server den
Datenwust überhaupt haben will, bevor der Upload losläuft.
Dummerweise muss der Client das initiieren, der Server hat da keinen
direkten Einfluss drauf.
Pragmatische Lösung:
Pack in die Upload-Form noch hidden-input-felder mit Session-ID oder
Username/passwort.
Akzeptier die anstelle des Digest-Auth beim Fileupload.
Unsicherer wird es dadurch nicht.
Läubi .. schrieb:
> Mal interessehalber: Warum forderst du nicht schon beim GET eine
> Autorisation?
Tue ich ja. Aber der Safari schickt dann trotzdem den Post ohne
Autorisation weg.
Dieses Problem habe ich NUR mit Safari-Browser. Alle anderen
funktionieren.
Ich habe das ganze unter Apache ausprobiert. D.h. ich schicke vom Safari
eine grosse Datei zum Apache-PC. Die Upload-Seite ist Digest gesichert.
Zunächst mal musste ich in der Apache-Konfiguration
stellen, da mit KeepAlive Connections der Safari sich wie Firefox
verhält, d.h. Credentials werden automatisch mitgeliefert.
Der Firefox liest den gesamten Post, bevor er 401 schickt, auch bei ganz
grossen Dateien (30MB).
>natürlich ignorieren aber nicht mittendrin die (TCP) Verbindung canceln.
Naja, ich dachte vielleicht hat TCP da eine Back-door.
Jürgen G. schrieb:
> d.h. Credentials werden automatisch mitgeliefert.
Und daran ist was das Problem?
Nico Sch. schrieb:
> Jürgen G. schrieb:
>> d.h. Credentials werden automatisch mitgeliefert.
>
> Und daran ist was das Problem?
Mit der Apache-Umgebung will ich nur wissen, wie sich ein Webserver
korrekt zu verhalten hat, wenn er einen Post wegen fehlender
Authorization abweisen muss.
Da der Apache default KeepAlive Connections verwendet, hat sich der
Safari anders verhalten, insofern, dass er die Authorization schon bei
allen Anfrage beim ersten Mal mitgeliefert hat.
Das musste ich ändern, da ich wollte, dass sich der Safari dem Apache
gegenüber GENAUSO verhält, wie dem Embedded Webserver gegengüber.
Deshalb habe ich beim Apache KeepAlive abgeschaltet.
Ich beobachtete, dass der Apache den gesamten (nicht authorisierten)
Datenwust eingelesen hat, bevor er 401-Antwort schickte.
Mein Problem ist jetzt, dass ich den Embedded-Server auch ändern muss,
dass er auch alles einliest bis er 401 schickt (was nicht einfach sein
wird, Code von Vorgängern),
oder eine andere Lösung wie ernst mit Hidden Fields angedeutet hat.
Gibt es eigentlich einen Grund weswegen der Embedded Server kein
keep-alive implementiert? Ansonsten ist das natürlich ein nicht so
schönes Verhalten vom Safari...
Außerdem solltest du wenn möglich den Embedded-Server http/1.1 Konform
machen:
http://www8.org/w8-papers/5c-protocols/key/key.html
Dann dürftest du nämlich auch "Expect and 100 (Continue)" nutzen, was
genau für solche Fälle gedacht ist.
Dafür benötigt man aber meine ich eine keep-alive Verbindung, und das
wird auch der Unterschied sein weswegen es ohne keep-alive nicht
wirklich rund läuft.
Läubi .. schrieb:
> Gibt es eigentlich einen Grund weswegen der Embedded Server kein
> keep-alive implementiert?
Er soll warscheinlich kurz und kompakt sein.
Mich wúrde interessieren, wie das andere Embedded Server handeln, z.B.
lwip (Lightweight IP). Weiß das jemand?
Jürgen G. schrieb:
> Mich wúrde interessieren, wie das andere Embedded Server handeln
Einfach mal bei denen nachschauen? ;)
Jürgen G. schrieb:
> Er soll warscheinlich kurz und kompakt sein.
Dann muss man das aber auch bis zum ende durchziehen! Das Implementierte
Verfahren funktioniert zumindest nur mit HTTP/1.1 ggf. wird keep-alive
benötigt (zumindest scheint der Safari das zu benötigen).
Jürgen G. schrieb:
> Mein Problem ist jetzt, dass ich den Embedded-Server auch ändern muss
Was ist das den für ein Gerät? Es ist ja nicht so, dass es nicht schon
fertige Webserver gäbe, in dem Bereich was "richtiges" zu bauen ist
schwer weil der Teufel oft im Detail steckt wie du schon festgestellt
hast.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|