2017-01-03 2 views
0

Ich erstelle ein Registrierungssystem für meine Webanwendung, in dem Benutzer einen Benutzernamen und ein Kennwort angeben. Diese Daten werden in einer postgresql Datenbank gespeichert. Ich verwende bcrypt einen gesalzenen Hash-Wert des Benutzers eingegebene Passwortes zu erzeugen, wieSo rufen Sie Kennwörter aus einer Datenbank ab

import bcrypt 
hashed = bcrypt.hashpw(PasswordFromWebForm.encode('UTF-8'), bcrypt.gensalt()) 

folgt Dadurch entsteht ein gesalzenes Kennwort ein, das ungefähr so ​​aussieht - b'$2b$12$GskbcRCMFHGuXumrNt3FLO'

ich in einer postgresql Datenbank diesen Wert am speichern. Wenn ein Benutzer versucht, sich beim System anzumelden, möchte ich als Nächstes seine Anmeldeinformationen überprüfen. Um dies zu tun, beabsichtige ich, etwas in der Art von zu tun -

import psycopg2 
conn = psycopg2.connect("dbname=test user=me") 
cur = conn.cursor() 

saltedpassword = cur.execute("SELECT saltedpassword FROM test WHERE loginid = %s", (LoginIDFromWebForm,)) 

if bcrypt.hashpw(PasswordFromWebForm.encode('UTF-8'), saltedpassword) == saltedpassword: 
    print("Success") 

Dies funktioniert nicht. Es löst den folgenden Fehler TypeError: Unicode-objects must be encoded before hashing aus.

Ich vermute, dass dieser Fehler ist, da die Variable saltedpassword speichert den Wert als Zeichenfolge wie diese "b'$2b$12$GskbcRCMFHGuXumrNt3FLO'" statt einfach nur b'$2b$12$GskbcRCMFHGuXumrNt3FLO' (die Anführungszeichen Beachten Sie die gesalzenen Passwort in der ehemaligen umschließenden)

Wie kann ich dieses Problem umgehen, Problem? Was ist der beste Weg, um das gesalzene Hash-Passwort in einer Datenbank zu speichern und wie gehe ich beim Abrufen davon vor, wenn es für die Verifizierung benötigt wird? Entschuldigung für die eher langwierige Frage - bitte helfen Sie.

Antwort

2

psycopg2 speichern Unicode-Text, müssen Sie das gesalzene Passwort vor dem Einsetzen in die Datenbank entschlüsseln:

cur.execute("INSERT INTO test VALUES (%s, %s)", 
      (LoginIDFromWebForm, saltedpassword.decode('ascii'))) 

Dies verhindert, dass die str() Umwandlung statt eingeführt wird (Ihr "b'....'" in der Datenbank zu geben).

Als nächstes, wenn Abfrage saltedpassword ist keine Zeichenfolge, weil cursor.execute() nicht die Ergebnisse zurückgibt; Es gibt stattdessen None zurück.

Sie werden zu fetch the result row brauchen:

cur.execute("SELECT saltedpassword FROM test WHERE loginid = %s", (LoginIDFromWebForm,)) 
row = cur.fetchone() 
if not row: 
    # No such login ID, handle accordingly 
saltedpassword = row[0].encode('ascii') 

Da Zeilen Unicode-Text enthalten, müssen Sie zuerst codieren zu Bytestring, bevor es zu bcrypt vorbei. Sie wollen auch die bcrypt.checkpw() Funktion verwenden, um das Passwort zu überprüfen:

if bcrypt.checkpw(PasswordFromWebForm.encode('UTF-8'), saltedpassword): 
    print("Success") 

bcrypt.checkpw()timing attacks vermeiden, wenn Strings zu vergleichen, was Ihr Code ist anfällig für.

+1

In Fairness, die bcrypt docs überprüfen Sie das Passwort mit 'if bcrypt.hashpw (Passwort, Hash) == hashed - https://pypi.python.org/pypi/bcrypt/2.0.0 – slim

+1

@slim: siehe Die aktualisierte Dokumentation für bcrypt 3: https://pypi.python.org/pypi/bcrypt/3.1.2, 'checkpw()' wurde in 3.1.0 hinzugefügt. –

+1

Ah ja, gerade gesehen, dass :) – slim

Verwandte Themen