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.
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.
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.
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.