Ich habe ein Django-Projekt, das ich in Kolben verschieben möchte. Das Problem ist, das Passwort auf die gleiche Weise zu verschlüsseln und zu entschlüsseln wie Django. Wird das möglich sein, die gleiche Ver- und Entschlüsselung wie in Django 1.10 zu implementieren. Das ist, ich möchte Passwort in der gleichen Weise in Flask erstellen und überprüfen, wie es mit Django getan wird. Googeln gab mir Passlib, aber der Doc ist nicht klar über die Django-Version (1.10). Danke.django 1.10 Passwort mit Kolben verwendet werden
Antwort
(Passlib Entwickler hier)
Passlib sollte definitiv in der Lage sein, diesen Fall zu behandeln, lassen Sie mich wissen, welche Teile der Dokumentation nicht klar waren, und ich kann versuchen, sie zu reinigen! (Neueste Dokumente sind unter http://passlib.readthedocs.io/en/stable/)
Dies sollte Ihnen den Einstieg (PassLib> = 1.7 vorausgesetzt) helfen.
Der einfachste Weg, um Dinge zu handhaben, ist eine CryptContext-Instanz zu erstellen, die mit allen Hash-Formaten konfiguriert ist, die Sie in Ihrer Datenbank haben.Es wird sich um Hashing & Verifikation von dort kümmern.
Für Django 1.10, möchten Sie wahrscheinlich so etwas wie die folgenden:
>>> from passlib.context import CryptContext
>>> pwd_context = CryptContext([
... default="django_pbkdf2_sha256",
... schemes=["django_argon2", "django_bcrypt", "django_bcrypt_sha256",
... "django_pbkdf2_sha256", "django_pbkdf2_sha1",
... "django_disabled"])
Sie können die ‚default‘ anpassen oben auf je nachdem, was Schema, das Sie wollen neue Hashes verwenden - auch Einfügen eines Nicht-django Hash-Format wie "bcrypt" in die Liste. Sie können auch alle entfernen, die nicht in Ihrer Datenbank vorhanden sind.
Sobald das Kontext-Objekt vorhanden ist, rufen Sie einfach .hash(), um das Passwort hash, w/automatische Salz Generation:
>>> hash = context.hash("foo")
>>> hash
'pbkdf2_sha256$29000$uzyeK0HKJIBR$XQtpjc9nfTdteF1fpk1Jk7FCePwB7S2JLuggiE8UBE4='
Und dann die folgenden einen Hash zu überprüfen:
>>> context.verify("foo", hash)
True
>>> context.verify("bar", hash)
False
Es gibt mehr Details in passlib CryptContext tutorial, wenn Sie brauchen.
Lässt ein wenig graben:
django/contrib/auth/base_user.py
:
class AbstractBaseUser(models.Model):
...
def set_password(self, raw_password):
self.password = make_password(raw_password)
self._password = raw_password
def check_password(self, raw_password):
"""
Return a boolean of whether the raw_password was correct. Handles
hashing formats behind the scenes.
"""
def setter(raw_password):
self.set_password(raw_password)
# Password hash upgrades shouldn't be considered password changes.
self._password = None
self.save(update_fields=["password"])
return check_password(raw_password, self.password, setter)
Grundsätzlich müssen wir überprüfen, wie make_password
und check_password
Werke, auf diese Weise können tun:
def make_password(password, salt=None, hasher='default'):
"""
Turn a plain-text password into a hash for database storage
Same as encode() but generates a new random salt.
If password is None then a concatenation of
UNUSABLE_PASSWORD_PREFIX and a random string will be returned
which disallows logins. Additional random string reduces chances
of gaining access to staff or superuser accounts.
See ticket #20079 for more info.
"""
if password is None:
return UNUSABLE_PASSWORD_PREFIX + get_random_string(UNUSABLE_PASSWORD_SUFFIX_LENGTH)
hasher = get_hasher(hasher)
if not salt:
salt = hasher.salt()
return hasher.encode(password, salt)
Und das Kontroll Passwort:
def check_password(password, encoded, setter=None, preferred='default'):
"""
Returns a boolean of whether the raw password matches the three
part encoded digest.
If setter is specified, it'll be called when you need to
regenerate the password.
"""
if password is None or not is_password_usable(encoded):
return False
preferred = get_hasher(preferred)
hasher = identify_hasher(encoded)
hasher_changed = hasher.algorithm != preferred.algorithm
must_update = hasher_changed or preferred.must_update(encoded)
is_correct = hasher.verify(password, encoded)
# If the hasher didn't change (we don't protect against enumeration if it
# does) and the password should get updated, try to close the timing gap
# between the work factor of the current encoded password and the default
# work factor.
if not is_correct and not hasher_changed and must_update:
hasher.harden_runtime(password, encoded)
if setter and is_correct and must_update:
setter(password)
return is_correct
Aa und das ist einfach zu viel :) Lasst uns auf den Haser konzentrieren!
Der django Standard Hasher ist: django.contrib.auth.hashers.PBKDF2PasswordHasher
- wenn Ihr Code Verwendung nicht einen Standard, Sie alle von ihnen in django/conf/global_settings.py
unter den PASSWORD_HASHERS
finden Lets überprüfen, was .verify
und .encode
auf dem Objekt Hasher tun.
def verify(self, password, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
assert algorithm == self.algorithm
encoded_2 = self.encode(password, salt, int(iterations))
return constant_time_compare(encoded, encoded_2)
Und das ist im Grunde raw
Kennwortprüfmerker, ist die codierte ein String (db gespeicherte Passwort in einem solchen Format: pbkdf2_sha256 $$$ (erinnere mich nicht genau)
Wie dem auch sei, was hier geschieht -. die django erstellt neues verschlüsseltes Passwort (aus rohem Passwort) und prüfen, ob die Ergebnisse die gleichen wie eine bereitgestellt
def encode(self, password, salt, iterations=None):
assert password is not None
assert salt and '$' not in salt
if not iterations:
iterations = self.iterations
hash = pbkdf2(password, salt, iterations, digest=self.digest)
hash = base64.b64encode(hash).decode('ascii').strip()
return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash)
und das ist ein Verfahren, das ein Passwort aus einem rohen Passwort erstellen wird;. Im Grunde brauchen Sie nur die Implementierung von pbkdf2
, die in django/utils/crypto.py
gefunden werden kann und soweit ich weiß verwendet es nur die Standard-hashlib-Bibliothek. Als django Open Source ist - können Sie diesen Code ausleihen, wie es ist :) (wahrscheinlich;))
Also alles summiert die oben:
import hashlib
import hmac
import struct
import binascii
import base64
def _long_to_bin(x, hex_format_string):
"""
Convert a long integer into a binary string.
hex_format_string is like "%020x" for padding 10 characters.
"""
return binascii.unhexlify((hex_format_string % x).encode('ascii'))
def _bin_to_long(x):
"""
Convert a binary string into a long integer
This is a clever optimization for fast xor vector math
"""
return int(binascii.hexlify(x), 16)
def pbkdf2(password, salt, iterations, dklen=0, digest=None):
"""
Implements PBKDF2 as defined in RFC 2898, section 5.2
HMAC+SHA256 is used as the default pseudo random function.
As of 2014, 100,000 iterations was the recommended default which took
100ms on a 2.7Ghz Intel i7 with an optimized implementation. This is
probably the bare minimum for security given 1000 iterations was
recommended in 2001. This code is very well optimized for CPython and
is about five times slower than OpenSSL's implementation. Look in
django.contrib.auth.hashers for the present default, it is lower than
the recommended 100,000 because of the performance difference between
this and an optimized implementation.
"""
assert iterations > 0
if not digest:
digest = hashlib.sha256
password = password
salt = salt
hlen = digest().digest_size
if not dklen:
dklen = hlen
if dklen > (2 ** 32 - 1) * hlen:
raise OverflowError('dklen too big')
l = -(-dklen // hlen)
r = dklen - (l - 1) * hlen
hex_format_string = "%%0%ix" % (hlen * 2)
inner, outer = digest(), digest()
if len(password) > inner.block_size:
password = digest(password).digest()
password += b'\x00' * (inner.block_size - len(password))
inner.update(password.translate(hmac.trans_36))
outer.update(password.translate(hmac.trans_5C))
def F(i):
u = salt + struct.pack(b'>I', i)
result = 0
for j in range(int(iterations)):
dig1, dig2 = inner.copy(), outer.copy()
dig1.update(u)
dig2.update(dig1.digest())
u = dig2.digest()
result ^= _bin_to_long(u)
return _long_to_bin(result, hex_format_string)
T = [F(x) for x in range(1, l)]
return b''.join(T) + F(l)[:r]
def make_password(password, salt, iterations=2, digest=hashlib.sha256):
hash = pbkdf2(password=password, salt=salt, iterations=iterations, digest=digest)
hash = base64.b64encode(hash).decode('ascii').strip()
return "%s$%d$%s$%s" % ('pbkdf2_sha256', iterations, salt, hash)
def check_password(raw_password, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
encoded_2 = make_password(raw_password, salt, int(iterations))
return encoded_2 == encoded
pwd = make_password(password='test', salt='salt', iterations=2, digest=hashlib.sha256)
# pbkdf2_sha256$2$salt$paft68X11fyh4GG9uMnHtk6pY9QFojoiDckOvLG6GoI=
print(check_password('test1', pwd))
# False
print(check_password('test', pwd))
# True
Btw, denken Sie daran, dass, wenn ein Passwort Ihr Salz machen sollte sei zufällig. Überprüfen Sie die .salt
Methode auf haser selbst. ;) Glückliche Codierung!
- 1. Django 1.10 makemigrations Fehler
- 2. Django 1.10 Muster umschreiben
- 3. Django 1.10 order_by() FieldError
- 4. Rückfehler in Django 1.10
- 5. Django 1.10 Übersetzung
- 6. Django 1.10 urls deprecation
- 7. NoReverseMatch Fehler Django 1.10
- 8. wie in django 1.10
- 9. Aktualisieren ModelForm Django 1.10
- 10. Benutzerdefinierte Seiten Fehler mit django 1.10
- 11. Heroku + Django + Kolben
- 12. Django 1.10 IntegrityError auf Register
- 13. Mit Render in render_to_string in Django 1.10
- 14. Django 1.10 super-einfache Filter
- 15. Passwort kann nicht eingegeben werden. (Erstellen eines Django-Admin-Superuser)
- 16. Django 1.10 - Aufrechterhaltung Kontextinformationen Objekt
- 17. Django 1.10 Auf Modelle ForeignKey
- 18. django 1.10 Medienbilder zeigen nicht
- 19. Installation fehlgeschlagen mit Django-Chronograph von pip in Django 1.10
- 20. Komplette "Django Kolben mit oauth Unterstützung" Beispiel
- 21. Kann Django mit py2exe verwendet werden?
- 22. Kolben-RESTful vs Kolben-Restless, die verwendet werden soll, und wenn
- 23. django 1.10 individuelles Benutzermodell und Benutzermanager
- 24. Heroku Fehler mit sammeln statisch mit Django 1.10
- 25. Warum nicht funktionieren Fluchtfilter in django 1.10
- 26. Django 1.10 Volltextsuche von UUIDField liefert Dataerror
- 27. django 1.10 postgres Volltextsuche funktioniert nicht
- 28. Django STATIC_URL funktioniert nur ohne 1.10 slash
- 29. django 1.10 url Dispatcher funktioniert nicht
- 30. Django 1.10 Mit einem Dropdown-Menü, um Abfragen zu filtern
danke @eli prost !! –