Аутентификация на основе токенов 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()