初始数据装置中的用户

72

我在fixtures/initial_data.json中默认创建了一些用户,以便进行一些测试。但是我遇到了密码生成的问题。我可以在“fields”中设置密码,但这样不会生成哈希密码:

[
    { "model": "auth.user",
        "pk": 1,
        "fields": {
            "username": "user1",
            "password": "password"
        }
    }
]

我需要一种生成用户密码的方法。我是否必须手动进行操作并生成一个字符串,例如像Django那样的{hash_method}${salt}${hashed_password}


我曾经使用过“django.contrib.auth.models.user”,但它并没有起作用! - mhyousefi
7个回答

110
在这种情况下,如果你只需要一些用户,可能更容易的方法是通过管理员创建一些虚假的用户账户(包括密码),然后使用 dumpdata 将这些用户转储到一个固定格式的文件中:
$ python manage.py dumpdata auth.User --indent 4 > users.json

该功能将自动为您创建夹具,并可在以后与 loaddata 一起使用。

(如果您需要大量测试用户,只需创建一个伪造账户并在其余夹具中使用哈希即可)

https://docs.djangoproject.com/en/dev/ref/django-admin/#dumpdata-appname-appname-appname-model


1
嗯 - 尝试为我做这件事在这里导致了一个空白的转储。 - Danny Staple
1
可以 - 从本地sqlite数据库工作正常,但不是主要的mysql数据库。这是一种安全特性吗? - Danny Staple
2
如果需要许多测试用户,你可以创建一个假帐户并在其余的装置中使用哈希。这个提示真的帮了我大忙!非常感谢 :) - daveoncode
这对我在PostgreSQL上起作用。我还能够使用在线JSON->YAML转换器,因为我喜欢使用YAML来进行固定装置。但请确保一切都正确缩进。 - Seth
1
这是我使用的方法,但我对此感到不安。此外,我必须从巨大的转储文件中提取我的“虚假用户”(请注意,这是真实世界的应用程序)。然后,我从转储中删除个人数据(可能会保留date_joined),并将其作为测试的fixture。然而,使用JSON,我甚至不能在密码哈希值旁边添加注释,明文值...我正在考虑直接使用密码,然后在测试的setUp方法中运行User.set_password(...)以供User.objects.all()使用。 - Tomasz Gandor

26

好的,我同意这些答案,但是让我回答一下最初的问题。

如何获取“Django将要进行哈希的”密码?

让我们看看文件django/contrib/auth/hashers.py

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 or blank then UNUSABLE_PASSWORD will be
    returned which disallows logins.
    """
    # ...

看下面这个示例会话:

./manage.py shell

>>> from django.contrib.auth.hashers import make_password, HASHERS
>>> make_password('test')
'pbkdf2_sha256$10000$vkRy7QauoLLj$ry+3xm3YX+YrSXbri8s3EcXDIrx5ceM+xQjtpLdw2oE='

# fix salt:
>>> make_password('test', 'abc')
'pbkdf2_sha256$10000$abc$MqJS5OAgSmf9SD9mfoY8fgLo8sSKmEcef0AjjMp1Q7w='

# use different (maybe faster, maybe unsafe!) hasher

In [12]: HASHERS
Out[12]:
{'bcrypt': <django.contrib.auth.hashers.BCryptPasswordHasher object at 0x29c6d50>,
 'crypt': <django.contrib.auth.hashers.CryptPasswordHasher object at 0x29c6f50>,
 'md5': <django.contrib.auth.hashers.MD5PasswordHasher object at 0x29c6e10>,
 'pbkdf2_sha1': <django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher object at 0x29c6bd0>,
 'pbkdf2_sha256': <django.contrib.auth.hashers.PBKDF2PasswordHasher object at 0x29c6cd0>,
 'sha1': <django.contrib.auth.hashers.SHA1PasswordHasher object at 0x29c6dd0>,
 'unsalted_md5': <django.contrib.auth.hashers.UnsaltedMD5PasswordHasher object at 0x29c6ed0>,
 'unsalted_sha1': <django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher object at 0x29c6e50>}

In [14]: [make_password('test', hasher=name) for name in HASHERS]
Out[14]:
['sha1$LdKsAbJRjlVP$2eb2346387cc510f576f2f11eebdfe18b20d1be1',
 'pbkdf2_sha256$10000$Ck8gtWQJnJ9x$M/OqP548d5KcPqFuVRgXb84unjYbYDH6oyimbDndE3k=',
 'pbkdf2_sha1$10000$BJqRu5OwylVF$hUvMLIzBujt9kPbML/dei1vLiMQ=',
 'crypt$$d9grSeqDhMFek',
 '098f6bcd4621d373cade4e832627b4f6',
 'sha1$$a94a8fe5ccb19ba61c4c0873d391e987982fbbd3',
 'bcrypt$$2a$12$WlJP5zm2lmdJ4g/pSE1xF.d/8w.XRT5mo/vGlkKdglBtzcxKw7XJS',
 'md5$txHYmSYJKhD4$69286d4a1abd348fbddc9df7687e2ed4']

您也可以手动使用哈希器的encode方法,但上述实用函数更加简便易用。


16

在编写测试的时候,我碰到了同样的问题。这是我在单元测试中的处理方式。

从管理后台创建数据并将它们转储到fixture中是可行的,但我不太喜欢依赖手动完成。所以这是我做的 -

像你已经做的那样创建fixture,然后在setUp方法中为用户设置密码。

user_fixture.json

[
    { "model": "auth.user",
        "pk": 1,
        "fields": {
            "username": "user1",
            "password": "password"
        }
    }
]

test_user.py

def setUp(self):
    self.User = get_user_model()

    # Fix the passwords of fixtures
    for user in self.User.objects.all():
        user.set_password(user.password)
        user.save()

通过这种方式,我可以干净地编写密码到fixture中,并在需要时引用它们,并通过编辑fixture文件来创建更多的fixture。


因为即使我使用Tomasz的答案(顺便说一下,这仍然是一个好答案,并且回答了原始问题),我仍然需要一个辅助脚本,所以我在我的初始setup.sh中使用./manage.py createsuperuser...,但使用类似Gaurav的帮助脚本来设置密码。其实itsafire的答案也很好,但我更喜欢使用这样的脚本。只是我的个人偏好。 - Harlin

6

补充@GauravButola的回答,我创建了一个自定义管理命令,可以一步加载fixture并修复密码。当不使用测试框架设置密码时,这非常有用。该示例与django 1.11和早期版本兼容。

在提供fixture的应用程序中添加您的管理命令(这是python3时间,因此我省略了init pys):

yourapp/
    models.py
    fixtures/
        initial_data.json
    management/
        commands/
            initdata.py

假设initdata.py的内容如下:

from django.core.management import BaseCommand, call_command
from django.contrib.auth.models import User
# from yourapp.models import User # if you have a custom user


class Command(BaseCommand):
    help = "DEV COMMAND: Fill databasse with a set of data for testing purposes"

    def handle(self, *args, **options):
        call_command('loaddata','initial_data')
        # Fix the passwords of fixtures
        for user in User.objects.all():
            user.set_password(user.password)
            user.save()

现在,您可以通过调用以下命令加载initial_data并获得有效密码:
./manage.py initdata

4

从数据库中导出用户信息:

$ python manage.py dumpdata auth.User --indent 4 > users.json

导入/加载指定的JSON样例数据:

$ python manage.py loaddata users.json

0
使用方法make_password(admin_password)。 它位于django.contrib.auth.hashers中。

-1

我相信你可以做到。这并不难。最简单的方法是查看函数user.set_password,然后看看他们是如何实现的。你可以在Python终端中调用该函数,然后将其复制到初始数据中!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接