Bedingung immer True

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

Hallo an alle. Bin ein wenig verzweifelt, weil ich das Problem einfach nicht erkennen kann. ICh weiß dass man Passwörter nicht in Klartext speichern sollte, aber das ist mir jetzt einfach mal schnuppe. Es geht um folgenden code:

Code: Alles auswählen

def loginRequest():
    
    try:    
        user = request.GET.get('user')
        password = request.GET.get('password')
    except:
        return "Bitte geben Sie sowohl einen Usernamen sowie ein Passwort an!"
    
    
    #Passwort ueberpruefen
    userDa = False
    passwordCorrect = False
    file = open('user/users.conf', 'r')
    for line in file:
        datensatz = line.split(' ')
        if datensatz[0] == user:
            userDa = True
            if datensatz[2] == password:
                passwordCorrect = True

#Hier ist die Bedingung immer True und das verstehe ich nicht. Selbst wenn das Passwort und der Username richtig sind.    
    if userDa == False or passwordCorrect == False:
        return 'username or password wrong'
Jemand eine Idee?

MfG
Martin
Zuletzt geändert von script_composer am Mittwoch 27. April 2011, 13:51, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Als erstes einmal: Verwende doch bitte Python-Code-Tags!

Hast Du denn mal geprüft, ob `userDa` und `passwordCorrect` an der Stelle wirklich `True` sind?

Was für ein Framework verwendest Du eigentlich? Es gibt ja Frameworks, die einem bereits eine vernünftige Session-Management Infrastruktur bieten.

Nebenbei sind Deine Namen nicht PEP8 konform. Bei Funktionen und Bezeichnern sollte man idR. das `names_with_underscores`-Schema benutzen.

Datein öffnet man mit dem

Code: Alles auswählen

with open() as handler:
    # handler ist hier das offene File-Object
Idiom.

Du kannst auch Formate wie INI, JSON, YAML oder XML oder stumpf CSV nutzen. Dann brauchst Du nicht umständlich parsen. Aber wie Du ja selber schon erkannt hast, ist das stumpfe Ablegen in einer Datei hier eher fehl am Platze.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Oh hatte den Python Tag übersehen.

Benutze Bottle was kein Session-Management mit bringt und wollte auf middleware verzichten. Möchte lieber grundlegende Kenntnisse sammeln anstatt mir durch vorgefertigte Systeme die ganze Arbeit abnehmen zu lassen. Darum fand ich Bottle so reizvoll, da immer noch ein großer Teil an einem selbst hängt.

Und ehrlich gesagt (sei mir bitte nicht böse) interessiert mich PEP8-Konformität recht wenig, da der gesamte Code nur durch mich eingesehen wird und es ein seeeehr kleines Projekt ist und bleibt.

Also ich habe nochmal geprüft und festgestellt, dass der Fehler hier entsteht:

Code: Alles auswählen

if datensatz[2] == password:
                passwordCorrect = True
also ist passwordCorrect immer False und das verstehe ich nicht.

Hier ist die Bedingung nie erfüllt. Ka warum. Habe sogar die Typen überprüft und den Inhalt via return() verglichen aber in jedem Fall war das ergebnis falsch.

Das Ablegen in einer einfach Datei kann auch Zweckmäßig sein oder? Wenn ich die Benutzer dort Manuell eintrage ist diese Variante bis auf die evt. fehlende Verschlüsselung zu Sicherheitszwecken doch voll OK, oder nicht?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

script_composer hat geschrieben: Möchte lieber grundlegende Kenntnisse sammeln anstatt mir durch vorgefertigte Systeme die ganze Arbeit abnehmen zu lassen. Darum fand ich Bottle so reizvoll, da immer noch ein großer Teil an einem selbst hängt.
Dann kannst Du Dir aber ja zumindest mal angucken, wie andere das so lösen. Z.B. hat flask da auch eine recht einfache, aber durchdachte Lösung implementiert, die auf gegen Race Conditions abgesichert ist. Man kann das Rad gerne neu erfinden; man muss dabei aber bedenken, dass andere schon ein verdammt gute Räder konstruiert haben - und wenn einem Erfahrung im Web- und Sicherheitsbereich fehlen, wird man eben keine gute Lösung finden. Daher ist das "Abgucken" gepaart mit Verstehen hier imho die sinnvollere Variante. Aber exakt diese Diskussion habe ich bezüglich bottle und Session-Management auch schon unlängst auf uu.de geführt...
script_composer hat geschrieben: Und ehrlich gesagt (sei mir bitte nicht böse) interessiert mich PEP8-Konformität recht wenig, da der gesamte Code nur durch mich eingesehen wird und es ein seeeehr kleines Projekt ist und bleibt.
Dann darfst Du aber hier im Forum von den Regulars keine Hilfe erwarten; denn hier müssen ja andere Deinen Code angucken, sobald Du Fragen hast. PEP8 nicht kennen oder auch fälschlicherweise ignorieren darf jeder; aber nach einem Hinweis darauf inkl. Erklärung, wieso das sinnvoll ist, sollte man das nicht ignorieren.
script_composer hat geschrieben: Also ich habe nochmal geprüft und festgestellt, dass der Fehler hier entsteht:

Code: Alles auswählen

if datensatz[2] == password:
                passwordCorrect = True
also ist passwordCorrect immer False und das verstehe ich nicht.
Hast Du dir die beiden Strings denn mal angeguckt? Wenn Du nur Username und PW in der Datei folgendermaßen ablegst, gibt es keinen Index 2!

Code: Alles auswählen

hugo 12345
test foo
Ich wiederhole dennoch mal, was gegen ein Standardformat spricht?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Lasse dir mal ``datensatz[2]`` und ``passwort`` in hexadezimaler Form, oder die einzelnen Zeichen mittels ``ord``, ausgeben. Vielleicht schleicht sich dort noch Whitespace ein.
script_composer hat geschrieben:Und ehrlich gesagt (sei mir bitte nicht böse) interessiert mich PEP8-Konformität recht wenig, da der gesamte Code nur durch mich eingesehen wird und es ein seeeehr kleines Projekt ist und bleibt.
Abgesehen davon, dass der Styleguide sehr sinnvoll ist: Dein Code wird nicht nur duch dich angeschaut, du hast hier bereits einen Ausschnitt gezeigt ;-) Mit konformem Code erhöhst du deine Chancen auf Antworten.

Sebastian
Das Leben ist wie ein Tennisball.
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Ach kommt bei dem kleinen CodeSchnipsel den ich euch gezeigt habe, ist die korrekte Variablenbezeichnung doch nicht sooo entscheident. Ob ich jetzt eine Variable halloWelt oder hallo_welt nenne ist doch relativ schnuppe bei einer so kurzen Funktion. Oder lieg ich da jetzt total falsch? Aber ich werde mir PEP8 mal genauer ansehen.

Race Conditions sind für mich kein Thema, da auf diese Datei lediglich lesender Zugriff besteht.
Du hast teilweise recht. Natürlich brauche ich nicht das Rad neu zu erfinden. Aber wenn man das Rad verstehen möchte kann man auch den Weg gehen das Rad selber zu bauen. Ich habe eine ungefähre Vorstellung was ich tun muss und wenn ich Fehler mache, kann ich aus diesen lernen. Aber mal so nebenbei. Was ist uu.de? die Seite kann ich nicht finden. Oder meinst du ubuntuuser?

Habe zwischen dem Usernamen und dem Passwort noch die Gruppenzugehörigkeit.
Also: user group password

Es spricht nichts gegen ein Standartformat. Aber was spricht denn gegen eine einfache Textdatei mit meiner Syntax, wie ich sie mag?


@ EyDU
Habe versucht mit return str(ord(password)) das zu überprüfen, aber bekomme folgende Fehlermeldung:

Code: Alles auswählen

TypeError: ord() expected a character, but string of length 5 found

Herzlichen Dank schonmal für die Hilfe ;) Hoffe ihr seid mir nicht böse wegen des PEP8 ;)
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

script_composer hat geschrieben:Habe versucht mit return str(ord(password)) das zu überprüfen, aber bekomme folgende Fehlermeldung:

Code: Alles auswählen

TypeError: ord() expected a character, but string of length 5 found
Die Fehlermeldung sollte aber eigentlich verständlich sein, wenn man weiß, was ord() eigentlich tut.

Code: Alles auswählen

for c in password:
    print ord(c)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ein ``print repr(whatever)`` sollte eigentlich reichen, wenn man sich Strings genauer anschauen will. `ord` finde ich ein bisschen zu viel des Guten.

Stefan
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Hier im Vergleich:

104
97
108
108
111


104
97
108
108
111
10

Also liegt es daran, dass am Ende der Reihe durch eine 10 die neue Linie angegeben wird. Ok Problem erkannt. Jetzt verstehe ich auch warum ihr mir ratet ein Standartformat zu nehmen ;)

Thanks

Herzlichen Dank für die schnelle Hilfe.

MfG
Martin
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Standard mit "d" bitte ;-)

Du hättest das Linebreak-Zeichen am Ende durch ein `strip()` entfernen sollen:

Code: Alles auswählen

datensatz = line.strip().split()
Das Space in `split()` ist übrigens nicht notwendig.

Ich meinte tatsächlich ubuntuusers.de.

Beachte bitte noch die Hinweise bezüglich des Ladens und Auslesens von Dateien. Man kann über die Zeilen von Textdateien direkt iterieren. Generell würde ich Dir auch empfehlen intern mit Unicode zu arbeiten.

Den Logikblock würde ich auch anders formulieren. Man kann die Abfrage nach gültigem Usernamen und PW auch in einer if-Bedingung formulieren und im Erfolgsfall aus der Funktion rausspringen. Dann kannst Du nach der Schleife den Fehlerfall behandeln.

Evtl. magst Du auch WTForms zur Validierung und zum Rendern der Formfelder nutzen; dazu gibt es ein nettes Beispiel aus der flask-Doku.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Werde mir die Sachen auf jeden Fall mal ansehen! Kleine Frage hätte ich noch:

ist SQlite3 in python bei multi-threading Race Conditions sicher?

Wenn nicht könnte ihr mir den link zu einer Anleitung geben wo erklärt wird wie das geht? Habe in der offiziellen Python-Anleitung nichts zu dem Thema gefunden.

Thanks 4 ALL!
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Wenn du Transaktionen benutzt, hält sich SQLite an ACID. Und bei CPython läuft sowieso immer nur ein Python-Thread gleichzeitig, bestenfalls das IO kann da also parallelisiert werden. Das ist nicht schön, macht aber CPython selbst thread-sicher.

Stefan
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Naja möchte ja paste-server verwenden. Dieser ist ja multithreaded. Also ich habe keine Ahnung ob der Transaktionen benutzt oder nicht -.- Sorry.
deets

sma hat geschrieben:Wenn du Transaktionen benutzt, hält sich SQLite an ACID. Und bei CPython läuft sowieso immer nur ein Python-Thread gleichzeitig, bestenfalls das IO kann da also parallelisiert werden. Das ist nicht schön, macht aber CPython selbst thread-sicher.
Hmnnaaaaaaja. Bloss weil es das GIL gibt, heisst es noch lange nicht, dass man in Python keine Race-Conditions oder Deadlocks bekommen kann. Die finden ja auch auf Ebenen statt, die oberhalb von einzelnen Byte-Code-Instruktionen stattfinden.

Code: Alles auswählen

if not etwas_in_der_db(): # jetzt kommt der context-switch
   lege_etwas_an() # und bumsfalleraaa, haben wir eine race-condition
deets

script_composer hat geschrieben:Naja möchte ja paste-server verwenden. Dieser ist ja multithreaded. Also ich habe keine Ahnung ob der Transaktionen benutzt oder nicht -.- Sorry.
Tut er nicht, der hat nuescht mit DBs zu tun. Wieso sollte er auch? Du *willst* ja kein wirklich komplettes Framework - also einfach mal davon ausgehen, dass du *alles* selbst machen musst.
deets

Oh, und weil ich's gerade sah: Formulare solltest du mittels POST abschicken, nicht GET. Das hat diverse Gruende, unter anderem Sicherheitsaspekte (Stichwort CSRF), und technische (bei GET kann es zu Beschraenkungen in der Maximalgroesse der erlaubten Daten kommen).
Benutzeravatar
script_composer
User
Beiträge: 29
Registriert: Mittwoch 13. April 2011, 12:42

Jo danke für den Hinweis aber wusste ich schon ;). Hatte das nur zu Testzwecken, damit ich einfach den Link aufrufen kann zum testen. Und einmal GET in POST zu ändern geht ja recht fix ;)

Trotzdem herzlichen Dank
Antworten