Вопрос

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

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

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

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

Это было полезно?

Решение

Для входа в систему вам не нужен пароль.А auth.login функция просто занимает User объект, который вы, предположительно, уже получаете из базы данных при включении учетной записи.Таким образом, вы можете передать это прямо 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'

Другие советы

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

Другой способ сделать это — создать HashModelBackend после бэкэндов пользовательской авторизации. 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

Начиная с 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)

Ответ на Дэнответ.

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

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 исходный код.Это актуально для Джанго 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 прекратит обработку при первом положительном совпадении.

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

Вы можете использовать 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': 'john.doe@mail.example.com',
        '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/) для большего.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top