bottlePy loginbereich/Server

Django, Flask, Bottle, WSGI, CGI…
Antworten
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Hallo an alle,

hatte zunächst mit Django gearbeitet aber mich doch dagegen entschieden. Django ist einfach ein bisschen too Much in meinen Augen und soviele Funktionen benötige ich nicht. Zudem fand ich Django für kleine Projekte eher umständlich? Habe daraufhin ein wenig mit bottle.py gearbeitet. Aber nur sehr wenig und im allgemeinen bin ich ein Neuling in Sachen web-Programmierung. Bitte seht mir daher mir meine vielleicht dummen Äußerungen und Fragen zu verzeihen. :D

Ich möchte gerne mit Bottle einen Loginbereich einrichten. Bei anderen Systemen bsp. php gibt es dafür ja Sessions. Habe auch auf bottlepy.org gelesen, dass es etwas ähnliches für bottle gibt. Allerdings habe ich mich gefragt, ob man das nicht wie im Tutorial einfach in Form von Cookies machen kann.

Ich habe wie gesagt kaum Ahnung. Wenn ich das mit Cookies mache, wie mache ich das so, dass es sicher ist? Muss ich die Cookies selber verwalten und sozusagen in ne Datenbank schreiben (oder einfach eine .txt)? In dem Tutorial sieht es stark vereinfacht aus, oder ist es einfach so einfach? (geile Frage ne) ;)

Bottle hat ja einen integrierten Server. Da ich nur eine CPU haben werde (Virtual Server), ist es mir egal wenn es nur ein Thread ist. Habe aber auch gelesen, dass wenn eine Anfrage da ist, dass dann keine zweite zu gleichen Zeit abgearbeitet wird. Stimmt das? Hieße das, wenn ich ein 100mb file zum Download anbiete, dass dann keiner mehr die Seite aufrufen könnte? Wenn das nämlich der Fall ist muss man ja im Prinzip eh einen WSGI-Server nehmen.

Ich hoffe ich konnte meine Fragen verständlich beschreiben.

MfG
Martin
deets

Du solltest es machen wie hier angegeben:

http://bottlepy.org/page/faq

und die Beaker-Session-Middleware verwenden. Dann musst du dich um diese Dinge nicht mehr kuemmern, und kannst alles bequem konfigurieren.

Was den Server angeht: wenn der bottle server single-threaded ist, dann hast du ein Problem bei laengeren Downloads. Threads sind auch auf einem Single-Core nuetzlich, wenn man blocking IO hat (was in diesem Fall zutrifft)

Es gibt da verschiedene Moeglichkeiten. Du kannst Apache/mod_wsgi nehmen. Damit hast du entweder multi-threaded oder multi-processed oder beides gemischt zur Auswahl. Dann gibt's noch die Moeglichkeit, statische Inhalte nicht von Python ausliefern zu lassen, sondern von einem Webserver wie Apache/NGINX. NGINX kannst du auch generell verwenden, statt Apache. Ich mache das, weil ich feststellen musste, das auf meinem VServer der Apache einfach zu dick war, egal wie sehr ich ihn runterkonfiguriert habe.

Wenn du nginx verwendest, dann bist du aber immer noch mit dem single-threaded Problem geschlagen. Denn das nginx.mod_wsgi ist *nicht* geeignet, das Problem zu loesen. Dafuer koenntest du dann zB paster verwenden, um bottle multi-threaded laufen zu lassen. Ich mache das fuer ein kleines Projekt das ich habe:

https://github.com/nwsgms/Save-the-News
Benutzeravatar
noisefloor
User
Beiträge: 3858
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

eine Cookie-basierte Login Seite ist mit Bottle nicht schwierig. Prinzipiell musst du:

1. eine Login-Seite haben
2. die Login-Daten gegen eine DB o.ä. verfifizieren
3. wenn ok einen Cookie setzen, der z.B. den Benutzernamen enthält
4. für alle "geheimen" Seiten vor dem Ausliefern prüfen, ob der Benutzer (dessen Namen du ja aus dem Cookie bekommst) die Seite sehen darf
5. ggf. eine Logout-Seite bauen, die den Cookie wieder löscht - sonst bleibt der i.d.R. bestehen, bis der Browser geschlossen wird

Einfach, wenn auch vielleicht bullet-proof...

Eine Middleware für Sessions brauchst du für sowas nicht. Das brauchst du nur, wenn du mehr Daten vorhalten willst, wie z.B. die letzten 10 besuchten Seiten.

Zum Server: es gibt ja noch eine Reihe weiterer Multithreaded-Server für WSGI. Für einen Teil bringt Bottle ja bereits Adapter mit. Was auch ginge ware z.B. http://gunicorn.org/.

Gruß, noisefloor
deets

noisefloor hat geschrieben:Hallo,

eine Cookie-basierte Login Seite ist mit Bottle nicht schwierig. Prinzipiell musst du:

1. eine Login-Seite haben
2. die Login-Daten gegen eine DB o.ä. verfifizieren
3. wenn ok einen Cookie setzen, der z.B. den Benutzernamen enthält
Und damit ein riesen Sicherheitsloch einbauen, denn der Cookie ist unverschluesselt, und ich muss meinen nur zB in "admin" umbenennen, und schon bin "drin".

Genau aus dem Grund sollte man sowas *nicht* selbst stricken. Beaker zB verschluesselt cookies fuer's Session-Management.

Natuerlich kann man das auch alles selbst machen, aber das gilt ja irgendwie fuer alles Programmierte. Und gerade, wenn man sich nicht auskennt, sollte man da lieber auf bewaehrtes setzen.
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Wenn ich die Cookies selbst verschlüsseln würde wäre es aber doch im Endeffekt genauso sicher oder? Ich meine so schwer kann das ja nicht sein ;). Nur ne theoretische Frage. Versuche mich lieber mal an beaker.

Danke euch allen für die super Antworten :)
deets

script_composer hat geschrieben:Wenn ich die Cookies selbst verschlüsseln würde wäre es aber doch im Endeffekt genauso sicher oder? Ich meine so schwer kann das ja nicht sein ;)
Na, wenn du etwas genauso machst wie jemand anderes, dann ist es ja genauso gemacht wie von jemand anderem... also auch genauso sicher.

Aber haettest du gewusst, dass du's machen musst? Ich vermute mal nicht. Denn sonst haettest du ja erst gar nicht gefragt, wie man sowas generell macht. Und da wird es noch so manch anderes geben, dass du nicht weisst - und darum im Zweifel nicht richtig machen wirst.

Das soll nicht heissen, dass du das nicht auch alles lernen koenntest. Aber es gibt genug anderes zu machen und zu lernen, statt schon geloeste Probleme nochmal zu loesen.
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Naja ich sag mal wenn man schon im August ne Ausbildung zum Fachinformatiker machen möchte sollte man schon versuchen so ein paar grundlegende Sicherheitsmechanismen selbst drauf zu haben. Zumindestens sollte man eine Idee davon haben worum es dabei geht.
Ich möchte schon möglichst viel wissen darum habe ich gefragt.

Abgesehen davon habe ich ja genau deswegen gefragt, was man beachten sollte, damit mir keine solchen Fehler passieren.

Aber ehrlich gesagt steig ich grad auch noch nicht mal bei Beaker durch :? :mrgreen:

Naja ok war auch eben Baumarkt, hatte also noch nicht soo viel Zeit ;)

Wünsche ne gute Nacht allen
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Kleiner Tipp: Bottle kann Cookies signieren, um sie fälschungssicher zu machen. Siehe http://bottlepy.org/docs/dev/tutorial.html#cookies

Und ja, es ist schwer so etwas richtig richtig zu machen. Experimentieren ist OK, aber produktiv sollte man eigene Lösungen nur einsetzen, wenn man genau weis, was man tut.
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Hallo.

Sehr interessantes Thema. Ich stelle mir momentan genau die selben Fragen wie der OP. Irgendwie habe ich das Vorgehen noch nicht so recht verstanden und konnte auch keine vernünftige Erklärung zu dem Thema finden. Ich habe daher noch einige Fragen...

In der Doku ist ja ein Beispiel für einen Login angegeben. Dieses kann ich soweit noch gut nachvollziehen. Ich frage mich nun aber wo genau die Verschlüsselung ansetzen würde? Was muss genau verschlüsselt werden? username? Und womit? Reicht auch die Signierung wie im Beispiel mit dem secret Attribut? Was heißt hier eigentlich signieren? Wird hier irgendwas gehasht? Wozu dient SECRETKEY?

Ich habe das Beispiel ein wenig umgeschrieben. Username und Passwort würden in einer realen Applikation sicherlich aus einer Datenbank gezogen. Der Einfachheit halber habe ich dies durch ein dict erzsetzt.

Code: Alles auswählen

users = {"HerrHagen": "123ABC",
         "OtherUser": "password"}

SECRETKEY = "123456"

def check_user_credentials(username, password):
    if username not in users: return False
    return password == users[username]

@route('/login')
def login():
    username = request.forms.get('username')
    password = request.forms.get('password')
    if check_user_credentials(username, password):
        response.set_cookie("account", username, secret=SECRETKEY)
        return "Welcome %s! You are now logged in." % username
    else:
        return "Login failed."

@route('/restricted')
def restricted_area(self):
    username = request.get_cookie("account", secret=SECRETKEY)
    if username:
        return "Hello %s. Welcome back." % username
    else:
        return "You are not logged in. Access denied."
Wie müsste auf Basis dieses Beispiels ein minimales sicheres Beispiel für einen Login-Bereich in bottle aussehen?

MFG HerrHagen
BlackJack

@HerrHagen: Ich würde vielleicht noch das Passwort "hashen", damit der Hash und nicht das Passwort im Klartext übertragen wird, und/oder sicherstellen dass die Verbindung über HTTPS verschlüsselt läuft. Ersteres setzt natürlich voraus, dass der Browser JavaScript kann, damit der Hash berechnet werden kann.

Ansonsten sieht das doch ganz okay aus so.

Signieren reicht. Das "Geheimnis" fliesst bei der Signierung und der Überprüfung selbiger ein. Das verlässt den Server nie und ein Angreifer müsste es kennen um ein gefälschtes Cookie zu signieren.
Benutzeravatar
noisefloor
User
Beiträge: 3858
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
deets hat geschrieben: Und damit ein riesen Sicherheitsloch einbauen, denn der Cookie ist unverschluesselt
Ich habe nie gesagt, dass der Cookie unverschlüsselt ist oder sein soll. ;-)

Bei uns im Intranet habe ich es auch zu umgesetzt wie Herr Hagen, nur dass die Benutzernamen und MD5-Hash des Passworts in einer DB liegen.

Gruß, noisefloor
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

HerrHagen hat geschrieben: In der Doku ist ja ein Beispiel für einen Login angegeben. Dieses kann ich soweit noch gut nachvollziehen. Ich frage mich nun aber wo genau die Verschlüsselung ansetzen würde? Was muss genau verschlüsselt werden? username? Und womit? Reicht auch die Signierung wie im Beispiel mit dem secret Attribut? Was heißt hier eigentlich signieren? Wird hier irgendwas gehasht? Wozu dient SECRETKEY?
Signieren heißt: Der Inhalt des Cookies ist gegen Manipulation geschützt.
Verschlüsseln heißt: Der Inhalt ist auch gegen das Auslesen geschützt.

Bottle signiert Cookies nur. Sie sind gegen Manipulation geschützt, können aber ausgelesen werden. Es ist also OK, nach dem Login den Benutzernamen als signierten Cookie zu speichern. Niemand kann sich unberechtigt als 'admin' anmelden, indem er den Cookie fälscht. Das Passwort sollte man aber NICHT im Cookie ablegen, da dieses von einem Angreifer ausgelesen werden könnte.

Der geheime Schlüssel wird benutzt, um die Signatur zu erstellen und zu prüfen. Er muss geheim und möglichst kompliziert sein, damit er nicht erraten werden kann. Bekommt ein Angreifer den geheimen Schlüssel in die Finger, kann er für beliebige Cookies gültige Signaturen erstellen.
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Danke für die Antworten. Ich glaube ich beginne zu verstehen.

Ich fasse nochmal zusammen. Bitte korrigiert mich wenn ich falsch liege:

Wenn request.set_cookie ein secret-Argument bekommt, nimmt bottle z.B. den username und verwurstet diesen mit dem secret-Argument (in diesem Fall SECRETKEY), hasht das Ganze und überträgt dies dann als cookie. Dadurch ist sichergestellt, dass nur der der SECRETKEY kennt, auch selber einen cookie dieser Art erzeugen kann. Kopieren könnte man ihn immer noch. Um sicherzustellen das der Cookie (des Admins bspw.) nicht durch eine man-in-the-middle Attacke abgehört wird, bräuchte man noch HTTPS.
SECRETKEY ist ein Schlüssel der für alle Benutzer gleichermaßen verwendet wird und hat nix mit dem Passwort des Benutzers zu tun. Dieses wird niemals zum Benutzer übertragen und sollte am besten nur als Hash in der DB gespeichert werden, da sonst jeder der Zugriff auf die DB hat (bzw. sich verschafft), Passwörter der Benutzer auslesen kann.
Prinzipiell könnte das Beispiel, das ich gepostet habe, auch so verwendet werden.
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Soweit korrekt.
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Nehmen wir mal an, ich möchte auf Middleware wie beaker verzichten. Das Projekt das ich erstelle beinhalten keine wirklich sensiblen Daten von daher kann ich mir Experimente erlauben ;) Zudem ist Beaker glaube ich nur für Python 2.x aber nicht für 3 (Weswegen ich letztendlich bei Bottle gelandet bin)

So wie ich das verstehe wird also durch die Secret_Key variante der Cookie verschlüsselt übertragen. Wenn jemand also den Cookie wieder zurück schickt wird dieser mit dem secret_key entschlüsselt und dann kann ich überprüfen ob dieser Nutzer existiert.
Wenn das so korrekt ist verzichte ich nämlich gerne auf Beaker und mache das ausschließlich mit Bottle.

Ob jemand den Cookie abfängt und sich damit einloggt, kann man eh nur durch SSL o.Ä. verhindern stimmts?
Also bietet die Secret_Key Option doch einen durchaus ausreichenden Schutz für das, was ich vorhabe, oder? (Also eben ohne SSL o.Ä.)

Des weiteren nehme ich an, dass ich diese "Sessions" abspeichern sollte (Für "Session abgelaufen" und anzeigen wer on ist und derartiges).
Kann man sowas eig. in einer Textdatei machen oder sollte ich das wirklich lieber per DB umsetzen? Ich denke SQLite sollte in diesem Fall ja gut geeignet sein oder?

Mal so zur Frage wie viele Programmierer arbeiten eig. an Bottle? Habe ich das nicht richtig in Erinnerung, dass du an dem Projekt beteiligt bist DefNull? Weil sobald ich meine Ausbildung hinter mir habe möchte ich mir evt. ein openSource Projekt suchen an dem ich mich beteiligen kann und gleichzeitig diese Erfahrungen aus dem Projekt für meine Interessen verwenden kann.
BlackJack

@script_composer: Das Cookie wird nicht verschlüsselt sondern signiert. Der Benutzer, oder auch Leute die den Datenverkehr mitlesen, können das Cookie also durchaus lesen/verstehen, aber eben keine Daten darin verfälschen.

Theoretisch könntest Du Session-bezogene Daten direkt im Cookie speichern, aber das muss ja jedes mal übertragen werden und darf auch nicht beliebig gross werden. Darum kann es günstiger sein das Cookie nur als als Schlüssel zu einem Datensatz in der Datenbank zu verwenden. Da kann man dann beliebig viele Daten zu einer Sitzung hinterlegen.

Textdatei wird problematisch wenn mehr als ein Benutzer an die Webanwendung herangeht. Da sollte man dann schon etwas verwenden was besser mit nebenläufigen Zugriffen klar kommt.
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Also enthielte der cookie einmal den Benutzernamen "John-Doe" und den Secret Key, der garantiert, dass dieser "John-Doe" Cookie vom Server generiert wurde?

Verstehe deinen Vorschlag. Find ich eig. recht einfach dieses System umzusetzen. Aber gut das ich auf Beaker verzichten kann.

Danke nochmal für eure Hilfe.
BlackJack

@script_composer: Nein das Cookie enthält natürlich nicht das Geheimnis. Wenn man das zum Benutzer schicken würde, wäre es ja kein Geheimnis mehr. Das Cookie enthält zum Beispiel den Namen und einen Hash-Wert als Signatur der aus dem Namen und dem Geheimnis berechnet wurde -- und zwar auf dem Server. Das wurde hier doch aber alles schon beschrieben…
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Ja so meinte ich das eigentlich auch. Sorry doof beschrieben von mir^^
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

@script_composer: Du kannst *heute* damit anfangen, bei Open-Source-Projekten mitzumachen. Vielleicht noch nicht produktiv Code beitragen, aber du kannst ja schonmal angucken wie das alles so organisiert wird, wie andere Leute Code schreiben (lesen, lesen, lesen) und so fort.

Ich schlage vor, dass du dich gleich mal bei GitHub anmeldest und dich ein wenig austobst :-)
Antworten