简体   繁体   中英

Using Django authentication system with existing hashed passwords

I have a very old Perl CGI system with a table of users. The passwords are stored as computed hashes using the crypt function. I am looking to migrate the system to Django, and I would like to keep the user data while using the Django table structure.

One option would be to copy all the user/password data an auth_user table and use a custom authentication function since I have existing password hashes.

Do I have a better option?

If I go with this option then how can it be implemented?

The documentation for writing up a custom authentication backend are in Customizing authentication in Django

Since Borodin asked and since you might find it handy to have a sample more specific to your request, I went ahead and wrote up an example that authenticates against a crypt -based file (eg, htpasswd ).

If the backend finds a user with a matching password in the crypt file, it looks for a standard Django user and returns it. If it can't find one it creates one. Obviously you would need to decide how you want to handle the actual details of your implementation.

./authbackend/__init__.py

import crypt
from django.conf import settings
from django.contrib.auth.models import User

class CryptBackend(object):
    def authenticate(self, request, username=None, password=None):
        crypt_file = getattr(settings, "CRYPT_DB", None)
        if crypt_file is None:
            return None

        password_match = False
        with open(crypt_file,"r") as f:
            for line in f:
                (user, crypted_pass) = line.rstrip().split(":")
                if user == username:
                    password_match = crypt.crypt(password, crypted_pass) == crypted_pass
                    break

        if not password_match:
            return None

        # found a match in our crypt database
        try:
            django_user = User.objects.get(username=username)
        except User.DoesNotExist:
            django_user = User.objects.create_user(username=username, email='', password=password)
            django_user.is_staff = True
            django_user.save()

        return django_user

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

That new custom backend is loaded based on additions to settings.py . In my example, I'm keeping the default Django backend and simply adding my new custom one. Django checks them in order, so it will try a standard Django authentication and if that doesn't work moves on to my custom one. The CRYPT_DB parameter is the path to the htpasswd file.

settings.py

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'authbackend.CryptBackend',
]

CRYPT_DB = '/path/to/your/passwd.file'

And for completeness, an example of the format ( htpasswd ) that the above is checking against.

passwd.file

jill:C.1oP2DOot4MY
jack:qJn7lPS/VNssM

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM