Вход в систему пользователя без пароля - PullRequest
64 голосов
/ 07 мая 2010

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

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

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

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

Ответы [ 5 ]

88 голосов
/ 07 мая 2010

Вам не нужен пароль для входа в систему. Функция 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'
25 голосов
/ 07 мая 2010

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

Другой способ сделать это - создать 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
24 голосов
/ 07 сентября 2016

Начиная с 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)
2 голосов

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

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

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 прекратит обработку при первом положительном совпадении.1021 * Будьте осторожны этот код будет аутентифицировать ваших пользователей даже с неверными паролями.

2 голосов
/ 21 декабря 2013

Вы можете использовать пакет 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/) для более.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...