Подтвердить что ты не робот

Ручная регистрация пользователя без пароля

Надеюсь, вы можете помочь мне составить наилучший способ реализовать руководство (инициированное сервером) логин без использования пароля. Позвольте мне объяснить рабочий процесс:

  • Пользовательские регистры
  • Спасибо! Письмо с ссылкой активации было отправлено blablabla
  • (Учетная запись существует, но она не включена)
  • Пользователь открывает электронную почту, нажимает ссылку
  • (Аккаунт включен)
  • Спасибо! Теперь вы можете использовать сайт

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

Я не могу использовать его пароль, поскольку он зашифрован в БД, является единственным вариантом написания собственного бэкапа аутентификации?

4b9b3361

Ответ 1

Вам не нужен пароль для входа в систему. Функция auth.login просто берет объект User, который вы, вероятно, уже получаете из базы данных, когда вы включаете учетную запись. Таким образом, вы можете передать это прямо для login в login.

Конечно, вам нужно быть очень осторожным, чтобы пользователь не мог подделать ссылку на существующую уже активированную учетную запись, которая бы автоматически регистрировала его как этого пользователя.

from django.contrib.auth import login

def activate_account(request, hash):
    account = get_account_from_hash(hash)
    if not account.is_active:
        account.activate()
        account.save()
        user = account.user
        login(request, user)

... так далее.

Отредактировано:

Хм, не заметил, что требование использовать authenticate из-за дополнительного свойства, которое он добавляет. Глядя на код, все, что он делает, это атрибут backend эквивалентный пути к модулю аутентифицирующего бэкенда. Таким образом, вы можете просто подделать его - перед тем как войти в систему, сделайте следующее:

user.backend = 'django.contrib.auth.backends.ModelBackend'

Ответ 2

Даниэль отвечает очень хорошо.

Другой способ сделать это - создать HashModelBackend после бэкэнда Custom Authorization https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#writing-an-authentication-backend следующим образом:

class HashModelBackend(object):
    def authenticate(self, hash=None):
        user = get_user_from_hash(hash)
        return user

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

И затем установите это в своих настройках:

AUTHENTICATION_BACKENDS = (
    'myproject.backends.HashModelBackend',
    'django.contrib.auth.backends.ModelBackend',
)

Тогда ваш взгляд будет примерно таким:

def activate_account(request, hash):
    user = authenticate(hash=hash)
    if user:
        # check if user is_active, and any other checks
        login(request, user)
    else:
        return user_not_found_bad_hash_message

Ответ 3

Начиная с Django 1.10, процесс был упрощен.

Во всех версиях Django, чтобы пользователь мог войти в систему, он должен быть аутентифицирован одним из бэкэндов вашего приложения (управляется параметром AUTHENTICATION_BACKENDS).

Если вы просто хотите принудительно войти в систему, вы можете просто заявить, что пользователь был аутентифицирован первым бэкэндом из этого списка:

from django.conf import settings
from django.contrib.auth import login


# Django 1.10+
login(request, user, backend=settings.AUTHENTICATION_BACKENDS[0])

# Django <1.10 -  fake the authenticate() call
user.backend = settings.AUTHENTICATION_BACKENDS[0]
login(request, user)

Ответ 4

Вы можете использовать пакет ska, в котором реализован вход без входа в Django без пароля. ska работает с токенами аутентификации, и его безопасность основана на SHARED_KEY, который должен быть одинаковым для всех участвующих сторон (серверов).

На стороне клиента (сторона, которая запрашивает логин без пароля), вы генерируете URL и подписываете его, используя ska. Пример:

from ska import sign_url
from ska.contrib.django.ska.settings import SECRET_KEY

server_ska_login_url = 'https://server-url.com/ska/login/'

signed_url = sign_url(
    auth_user='test_ska_user_0',
    secret_key=SECRET_KEY,
    url=server_ska_login_url
    extra={
        'email': '[email protected]',
        'first_name': 'John',
        'last_name': 'Doe',
    }
)

Срок действия токена по умолчанию составляет 600 секунд. Вы можете настроить это, доказав lifetime аргумент.

На стороне сервера (сайт, на который пользователи входят), имея в виду, что вы правильно установили ska, пользователь входит в систему после посещения URL-адреса, если он существует (совпадение имени пользователя) или иным образом - создан. Есть 3 обратных вызова, которые вы можете настроить в настройках Django вашего проекта.

  • USER_GET_CALLBACK (строка): срабатывает, если пользователь был успешно извлечен из базы данных (существующий пользователь).
  • USER_CREATE_CALLBACK (строка): срабатывает сразу после создания пользователя (пользователь не существует).
  • USER_INFO_CALLBACK (строка): срабатывает при успешной аутентификации.

Смотрите документацию (http://pythonhosted.org/ska/) для получения дополнительной информации.

Ответ 5

Ответ на дан ответ.

Способ записи вашего бэкэнда:

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

class HashModelBackend(ModelBackend):

def authenticate(self, username=None, **kwargs):
    UserModel = get_user_model()
    if username is None:
        username = kwargs.get(UserModel.USERNAME_FIELD)
    try:
        user = UserModel._default_manager.get_by_natural_key(username)
        return user
    except UserModel.DoesNotExist:
        return None

Ответ основан на django.contrib.auth.backends.ModelBackend исходном коде. Это актуально для django 1.9

И я бы предпочел разместить пользовательский бэкэнд ниже стандартного django:

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'yours.HashModelBackend',
]

поскольку активация учетной записи менее возможна, чем сама учетная запись. Согласно https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#specifying-authentication-backends:

Порядок AUTHENTICATION_BACKENDS имеет значение, поэтому, если одно и то же имя пользователя и пароль действительны в нескольких бэкэндах, Django прекратит обработку в первом положительном совпадении.

Будьте осторожны этот код будет аутентифицировать ваших пользователей даже с неправильными паролями.