Аутентификация на основе токенов Django без модели пользователя

Я использую аутентификацию на основе токенов Django. (Токен JWT генерируется сторонней организацией, такой как AWS Cognito, мы просто проверим подпись и срок действия).

Это REST-приложение не будет иметь пользовательских моделей, которые должны проходить аутентификацию только с помощью токена JWT.

class JSONWebTokenAuthentication(TokenAuthentication):
    def authenticate_credentials(self, jwtToken):
        try:
            payload = jwt.decode(jwtToken, secret_key,verify=True)
            # user = User.objects.get(username='root')
            user =  AnonymousUser()
        except (jwt.DecodeError, User.DoesNotExist):
            raise exceptions.AuthenticationFailed('Invalid token)
        except jwt.ExpiredSignatureError:
            raise exceptions.AuthenticationFailed('Token has expired')
        return (user, payload)

В представлениях:

@api_view(["POST"])
@authentication_classes((JSONWebTokenAuthentication,))
@permission_classes((AllowAny,))

Выше процесса, не отслеживает токен вообще. С / без токена, звонки APi работают. Если я сделаю два изменения ниже, это работает.

user = User.objects.get(username='root')
#user = AnonymousUser()
@permission_classes((IsAuthenticated,))

Один из способов сделать это - иметь хотя бы одного пользователя в моем приложении и ссылаться на этого пользователя [Это веб-приложение может масштабироваться до любого количества экземпляров, когда это необходимо, поэтому вставка одного и того же пользователя с тем же "именем пользователя" должна быть автоматизирована. ]. Но вместо этого я могу устранить концепцию "Пользователь" в аутентификации?

5 ответов

Решение

Среда Django REST предполагает, что запросы аутентифицируются на основе пользователя, но они обеспечивают поддержку аутентификации анонимных запросов. Но это отличается от стандартного предположения о том, что "проверяющий (django) пользователь является подлинным", предоставляя анонимному пользователю определенные разрешения. Проблема с вашим первым делом - разрешение разрешения "Allow Any".

Я предлагаю иметь фиктивного пользователя Django. (это не останавливает вас от масштабирования до любого количества экземпляров).

использование

user = User.objects.get_or_create(username='whatever')[0]

вместо

user =  AnonymousUser()

Теперь измените разрешение декоратора на

@permission_classes((IsAuthenticated,))

Этот пользователь не может быть авторизован кем-либо, пока вы не установите пароль, более того, вход в систему, так как этот пользователь не предоставит вам доступ к вашему вызову API. Единственный способ получить доступ к вашему API - это отправить действительный токен.

Надеюсь это поможет.

Иногда вам просто действительно не нужен Пользователь, например, связь между сервером. Вот решение.

Переопределите свойство is_authenticated AnonymousUser, и все готово.

from django.contrib.auth.models import AnonymousUser

class ServerUser(AnonymousUser):

    @property
    def is_authenticated(self):
        # Always return True. This is a way to tell if
        # the user has been authenticated in permissions
        return True

Просто верните этот новый тип пользователя в свою пользовательскую аутентификацию.

class CustomServerAuthentication(authentication.BaseAuthentication):
    keyword = 'Token'

    def authenticate(self, request):
        auth = get_authorization_header(request).split()

        if not auth or auth[0].lower() != self.keyword.lower().encode():
            raise exceptions.AuthenticationFailed('Invalid token header')

        if len(auth) == 1:
            raise exceptions.AuthenticationFailed('Invalid token header. No credentials provided.')

        elif len(auth) > 2:
            raise exceptions.AuthenticationFailed('Invalid token header. Token string should not contain spaces.')

        token = auth[1].decode()

        if not (settings.CUSTOM_SERVER_AUTH_TOKEN == token):
            raise exceptions.AuthenticationFailed('You do not have permission to access this resource')

        user = ServerUser()

        return user, None

Используя https://github.com/SimpleJWT/django-rest-framework-simplejwt, вы можете установитьDEFAULT_AUTHENTICATION_CLASSESиспользовать JWTTokenUserAuthentication и просто проверять токен даже без пользователя.

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

вы можете использовать модель пользователя без вставки данных в базу данных:

      user = User(id=22,username="someone")

вместо:

      user = User.objects.get_or_create(username="someone")

или же

       AnonymousUser()
Другие вопросы по тегам