2013-05-02 14 views
6

Die Regierung meines Landes hat die HTTPS-Geschwindigkeit eingeschränkt, um den Zugriff auf sichere Webdienste außerhalb des Irans zu blockieren. Jetzt haben meine Kunden Schmerzen, weil sie sich in ihre Konten eingeloggt haben. Ich weiß, dass aktuelle Kontokennwörter verschlüsselt und gesalzen sind mit pbkdf2_sha256 Algorithmus und es gibt einige Javascript/jQuery-Bibliotheken, um sha256 Hashes zu verdauen.Verwenden Sie sha256 Hashes anstelle von Klartextpasswörtern

Meine Frage: Gibt es einen schmerzlosen Weg (der das Umschreiben/Ändern der ursprünglichen django.contrib.auth nicht erfordert), um sha256-Hashes zu verwenden, die von AJAX-Anfragen als Login-Passwort gesendet werden?

Update: Ich plane, meine Websites innerhalb des Irans zu hosten (das ist 5-mal teurer und natürlich von der Regierung kontrolliert), aber mindestens HTTPS-Protokoll ist nicht beschränkt. Das Senden von Passwörtern im Klartext oder verdaut über den HTTP-Kanal ist ohnehin unsicher. Während ich als Webentwickler (und nicht als Netzwerkexperte) denke, dass sie die Hashes/Session IDs/Cookies jederzeit sammeln/schnüffeln können, benötigt das Lösen des Problems ein ausgefeiltes Wissen und Anstrengungen und schließlich erfordert meine Site nicht diese Sicherheitsstufe . Wir leben auf verschiedenen Planeten.

+1

Willkommen bei Stack Overflow. Bitte [versuchen Sie, eine höflichere Sprache zu verwenden] (http://meta.stackexchange.com/questions/2232/are-expletives-allowed-on-se-sites/222233#22233). – nnnnnn

+3

Danke. Entschuldigung für Worte. Ich schlafe seit 33 Stunden nicht mehr und schlage meinen Kopf für ein Problem an die Wand, das nicht durch meine Schuld verursacht wurde. – GhaghaSibil

Antwort

3

Sie können Ihren eigenen Authentifizierungs-Backend schreiben rohe Passwörter zu verwenden:

from django.contrib.auth import backends 
from django.contrib.auth.models import User 

class RawPasswordUser(User): 
    class Meta: 
     proxy = True 

    def set_password(self, raw_password): 
     # default implementation made a hash from raw_password, 
     # we don't want this 
     self.password = raw_password 

    def check_password(self, raw_password): 
     # same here, don't make hash out of raw_password 
     return self.password == raw_password 

class ModelBackend(backends.ModelBackend): 
    def authenticate(self, username=None, password=None): 
     try: 
      user = RawPasswordUser.objects.get(username=username) 
      if user.check_password(password): 
       return user 
     except RawPasswordUser.DoesNotExist: 
      return None 

    def get_user(self, user_id): 
     try: 
      return RawPasswordUser.objects.get(pk=user_id) 
     except RawPasswordUser.DoesNotExist: 
      return None 

In Einstellungsdatei:

AUTHENTICATION_BACKENDS = (
    # ModelBackend from project_root/auth/backends.py 
    'auth.backends.ModelBackend', 
) 

Wenn Sie jetzt authenticate Benutzer in Ihren Ansichten, Sie RawPasswordUser Instanzen erhalten. Das Gleiche gilt für login_required Dekorateur, request.user zeigt auf die Proxy-Klasse.

Weitere Informationen finden Sie unter documentation.

Für Django 1.5 + there is also an option ersetzen Sie das Standardbenutzermodell durch ein benutzerdefiniertes, aber um bestehende Benutzer beizubehalten, müssen Sie sie irgendwie migrieren, siehe this question.


Eigentlich können Sie Benutzerkennwörter nicht unverändert lassen.

standardmäßig Django speichert Passwörter in folgendem Format:

Algorithmus $ Iterationen $ salt $ hash

Was bedeutet:

  • Sie können nicht nur Passwörter regenerieren aus Original-Hashes, da Sie die Originale nicht haben.

  • Sie werden auch nicht in der Lage sein, den gleichen Hash auf der Client-Seite zu generieren, ohne das Salz zu kennen. Sie könnten es an die Client-Seite weitergeben, aber Salz sollte ein Geheimnis sein, also ist es unklug, es über einen unverschlüsselten Kanal zu tun.

Die einfachste Lösung, die ich sehe, ist aktuell Django Verhalten zu halten, wie Tadeck in den Kommentaren vorgeschlagen wurde, in den clientseitigen und Kraft Benutzer Hashing ihre Passwörter zu ändern.

Nun, es ist nicht wirklich eine Lösung, denn ein Angreifer kann verdaute Passwörter abfangen und sie direkt verwenden, aber Sie erwähnten es Ihre Frage Update. Da Sie nicht so viel Wert auf Sicherheit legen, können Sie auch public key encryption in JavaScript auschecken.


Eine weitere Lösung von Tadeck vorgeschlagen ist OAuth-ähnlichen Dienst zu verwenden, die sich wie etwas aussehen könnte:

def index(request): 
    access_token = request.REQUEST.get('token', None) 
    if not access_token: 
     return redirect('login') 

    # Custom authentication backend that accepts a token 
    # and searches for a user with that token in database. 
    user = authenticate(access_token) 
    if not user: 
     return redirect('login') 

    return render(...) 

def auth(request): 
    ''' This ajax-view has to be encrypted with SSL.''' 
    # Normal Django authentication. 
    user = authenticate(request.POST['username'], request.POST['password']) 

    # Authentication failed 
    if user is None: 
     return json.dumps({'error': '...'}) 

    # generate, save and return token in json response 
    token = UserToken(user=user, value=generate_token()) 
    # token.expires_at = datetime.now() + timedelta(days=1) 
    token.save() 

    return json.dumps({'token': token.value}) 

Ein noch angegriffen kann ein Zugriffstoken abfangen, aber es ist ein bisschen besser als das Abfangen Passwort-Hash.

+0

Ich würde das 'except' direkt unter' user = User.objects.get (...) ' –

+0

platzieren Ist es erforderlich, die aktuellen Backend-Datensätze zu ändern? Ich meine, wenn das neue Backend verwendet wird, sollten die derzeitigen Benutzer ihre Passwörter ändern. Kann ich ein Skript schreiben, um sie zu konvertieren? – GhaghaSibil

+0

Passwörter bleiben eine Hashes, Sie Ihre Client-Seite sendet die gleichen Hashes, dann müssen Sie nichts konvertieren. Wenn Hashes unterschiedlich sind, können Sie in 'python manage.py shell' konvertieren,' django.contrib.auth.models.User' importieren und ändern, wie Sie möchten. – gatto

Verwandte Themen