Пользователи в исходном хранилище данных - PullRequest
50 голосов
/ 05 ноября 2011

Я создаю несколько пользователей по умолчанию в моем fixtures/initial_data.json, чтобы иметь несколько "субъектов" тестирования. Проблема, с которой я сталкиваюсь - это генерация пароля. Я мог бы установить пароль в «полях», но это не сгенерирует хешированный пароль:

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

Мне нужен способ генерации пароля пользователя. Нужно ли делать это вручную и генерировать строку типа {hash_method}${salt}${hashed_password}, как это делает Django?

Ответы [ 6 ]

91 голосов
/ 05 ноября 2011

Что может быть проще в этом случае (и если вам нужно всего несколько пользователей), это создать несколько поддельных учетных записей пользователей через администратора (включая пароли), а затем вывести пользователей в файл фикстур, используя 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

18 голосов
/ 05 мая 2014

ОК, я согласен с ответами, но позвольте мне ответить на оригинальные вопросы.

Как получить пароль "как бы его хешировал Джанго"?

Давайте посмотрим файл 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 вручную, но с помощью вышеприведенной служебной функции вы сможете более просто разобраться.

12 голосов
/ 16 июня 2016

Я столкнулся с той же проблемой при написании приборов для тестов.Вот как я справляюсь с этим в модульных тестах.

Создание данных от администратора и сброс их в работу прибора, но мне не очень нравится зависеть от ручного выполнения этого.Итак, вот что я делаю -

Создайте прибор так же, как вы сделали, а затем в методе setUp, set_password s для пользователей.

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()

Таким образом, я могу аккуратно написать пароли в приборе и обращаться к ним, когда мне нужно исоздать больше приборов просто отредактировав файл приборов.

4 голосов
/ 19 мая 2017

Добавляя к ответу @GauravButola, я создал собственную команду управления, чтобы загрузить прибор и исправить пароли за один шаг. Это полезно, когда не используется среда тестирования для настройки паролей. Пример работает с django 1.11 и, возможно, более ранними версиями.

В вашем приложении, предоставляющем прибор, добавьте команду управления (это 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()

Теперь вы можете загрузить исходные_данные и иметь действительные пароли, позвонив по номеру:

./manage.py initdata
2 голосов
/ 02 марта 2018

Дамп информации о пользователях из базы данных:

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

Импорт / загрузка данных, специфичные для JSON:

$ python manage.py loaddata users.json
0 голосов
/ 05 ноября 2011

почти уверен, что вы делаете.это не должно быть так сложно.Проще всего было бы посмотреть на функцию user.set_password Я думаю, что это так, и посмотреть, как они это делают.Вы, вероятно, можете вызвать функцию из терминала Python, а затем скопировать ее в свои исходные данные!

...