Как я могу аутентифицировать пользователя с помощью параметра запроса на любом URL-адресе? - PullRequest
2 голосов
/ 26 мая 2020

Допустим, пользователь попадает на https://example.com/any/page?token=hhdo28h3do782.

Какой рекомендуемый способ аутентификации и входа пользователя с помощью строки запроса?

Я думал о создании своего рода уловки- весь вид (я также хотел бы знать, как это сделать: D), который вызывает authenticate(). Тогда я бы установил собственный бэкэнд, который будет аутентифицировать пользователя.

Это идеальный способ достичь того, чего я хочу?

Ура!

Ответы [ 3 ]

3 голосов
/ 26 мая 2020

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

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

# my_project/authentication_backends.py
from django.contrib import auth
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
from django.contrib.auth.middleware import AuthenticationMiddleware

TOKEN_QUERY_PARAM = "token"

class TokenMiddleware(AuthenticationMiddleware):
    def process_request(self, request):
        try:
            token = request.GET[TOKEN_QUERY_PARAM]
        except KeyError:
            # A token isn't included in the query params
            return

        if request.user.is_authenticated:
            # Here you can check that the authenticated user has the same `token` value
            # as the one in the request. Otherwise, logout the already authenticated
            # user.
            if request.user.token.key == token:
                return
            else:
                auth.logout(request)

        user = auth.authenticate(request, token=token)
        if user:
            # The token is valid. Save the user to the request and session.
            request.user = user
            auth.login(request, user)

class TokenBackend(ModelBackend):
    def authenticate(self, request, token=None):
        if not token:
            return None

        try:
            return User.objects.get(token__key=token)
        except User.DoesNotExist:
            # A user with that token does not exist
            return None

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

Теперь вы можете добавить пути к AUTHENTICATION_BACKENDS и MIDDLEWARE в свой settings.py в дополнение к любым существующим серверным процессам или промежуточному программному обеспечению, которое у вас уже может быть. Если вы используете значения по умолчанию, это будет выглядеть так:

MIDDLEWARE = [
    # ...
    "django.contrib.auth.middleware.AuthenticationMiddleware",

    # This is the dotted path to your backend class. For this example,
    # I'm pretending that the class is in the file:
    #     my_project/authentication_backends.py
    "my_project.authentication_backends.TokenMiddleware",

    # ...
]

AUTHENTICATION_BACKENDS = [
    "django.contrib.auth.backends.ModelBackend",
    "my_project.authentication_backends.TokenBackend",
]
2 голосов
/ 26 мая 2020

Я предполагаю, что вы используете Django REST Framework , а также включили механизм TokenAuthentication в своем проекте. Если это так, go вперед с этим,

from rest_framework.authentication import TokenAuthentication


class QueryParamAuthentication(TokenAuthentication):
    query_param_name = 'token'

    def authenticate(self, request):
        token = request.query_params.get(self.query_param_name)
        if token:
            return self.authenticate_credentials(token)
        return None

, а затем измените DRF DEFAULT_AUTHENTICATION_CLASSES на

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'dotted.path.to.QueryParamAuthentication'
    ),
    # rest of your DRF settings...

}

Обновить

чтобы сделать это без DRF, вы должны написать бэкэнд пользовательской модели (что немного длинновато c)

Обратитесь : Написание бэкэнда аутентификации

1 голос
/ 26 мая 2020

Итак, начнем со способа управления вашими токенами. Вот базовая c модель:

class Token(models.Model):
    code = models.CharField(max_length=255)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    expires = models.DateTimeField()

Для проверки действительности токенов может быть создан пользовательский сервер аутентификации:

class TokenAuthenticationBackend(ModelBackend):
    def authenticate(self, request, token=None):
        try:
            token = Token.objects.get(code=token, expires__gte=now())
        except Token.DoesNotExist:
            return None
        else:
            return token.user

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

class UrlTokenAuthenticationMixin:
    def dispatch(self, request, *args, **kwargs):
        if 'token' in request.GET:
            user = authenticate(request, request.GET['token'])
            if user:
                login(request, user)
        return super(UrlTokenAuthenticationMixin, self).dispatch(request, *args, **kwargs)

Чтобы использовать это в данном представлении, просто объявите свои представления следующим образом:

class MyView(UrlTokenAuthenticationMixin, TemplateView):
    # view code here

Например.

Альтернативный способ реализовать это в качестве универсального комплексного решения - использовать промежуточное программное обеспечение, а не миксин:

class TokenAuthMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if 'token' in request.GET:
            user = authenticate(request, request.GET['token'])
            if user:
                login(request, user)
        return self.get_response(request)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...