简体   繁体   English

使用Django身份验证系统和现有的哈希密码

[英]Using Django authentication system with existing hashed passwords

I have a very old Perl CGI system with a table of users. 我有一个带有用户表的非常老的Perl CGI系统。 The passwords are stored as computed hashes using the crypt function. 使用crypt函数将密码存储为计算得出的哈希值。 I am looking to migrate the system to Django, and I would like to keep the user data while using the Django table structure. 我希望将系统迁移到Django,并且我想在使用Django表结构时保留用户数据。

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. 一种选择是将所有用户/密码数据复制到auth_user表中,并使用自定义身份验证功能,因为我已有密码哈希。

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 编写自定义身份验证后端的文档在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 ). 由于Borodin提出了要求,并且由于您可能会发现有一个更具体针对您的请求的示例很方便,因此我继续写了一个示例,该示例针对基于crypt的文件(例如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. 如果后端在crypt文件中找到密码匹配的用户,则它将寻找标准的Django用户并返回。 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 ./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 . 该新的自定义后端将根据settings.py添加内容进行加载。 In my example, I'm keeping the default Django backend and simply adding my new custom one. 在我的示例中,我保留了默认的Django后端,并仅添加了新的自定义后端。 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. Django会按顺序检查它们,因此它将尝试标准的Django身份验证,如果不起作用,请转到我的自定义身份验证。 The CRYPT_DB parameter is the path to the htpasswd file. CRYPT_DB参数是htpasswd文件的路径。

settings.py 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. 为了完整htpasswd ,上面要检查的格式( htpasswd )的示例。

passwd.file passwd.file

jill:C.1oP2DOot4MY
jack:qJn7lPS/VNssM

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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