Здравствуйте!
Решил запилить авторизацию на backend'e через библиотеку
drf-simplejwt.
До подключения библиотеки уже была реализована своя модель User через AbstractBaseUser:
from django.conf import settings
from django.contrib.auth.models import (
AbstractBaseUser, BaseUserManager, PermissionsMixin
)
from django.db import models
class UserManager(BaseUserManager):
def create_user(self, username, email, password=None):
""" Создает и возвращает пользователя с имэйлом, паролем и именем. """
if username is None:
raise TypeError('Users must have a username.')
if email is None:
raise TypeError('Users must have an email address.')
user = self.model(username=username, email=self.normalize_email(email))
user.set_password(password)
user.save()
return user
def create_superuser(self, username, email, password):
""" Создает и возввращет пользователя с привилегиями суперадмина. """
if password is None:
raise TypeError('Superusers must have a password.')
user = self.create_user(username, email, password)
user.is_superuser = True
user.is_staff = True
user.save()
return user
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(db_index=True, max_length=255, unique=True)
first_name = models.TextField(max_length=32)
last_name = models.TextField(max_length=32)
email = models.EmailField(db_index=True, unique=True)
telephone = models.CharField(max_length=15)
avatar = models.ImageField(upload_to='users_avatars')
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
def __str__(self):
return self.email
def get_full_name(self):
return self.first_name + " " + self.last_name
def get_short_name(self):
return self.username
И в бд уже был суперюзер.
После подключения
drf-simplejwt сделал миграции, настроил urls, вроде все как положено.
general urls.py:
from django.contrib import admin
from django.urls import path, include
from .views import *
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('authentication/', include('authentication.urls'))
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
authentication's urls.py:
from django.urls import path
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView)
from authentication.views import register
app_name = 'authentication'
urlpatterns = [
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
# Submit your refresh token to this path to obtain a new access token
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
# Register a new user
path('register/', register, name='register_view'),
]
settings.py:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
'rest_framework_simplejwt.token_blacklist',
'rest_framework',
'authentication',
]
AUTH_USER_MODEL = 'authentication.User'
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}
Собственно говоря это вроде всё по настройке.
Так в чем гвоздь программы: при попытке аутенфикации он выкидывет мне ошибку в консоли 400 Bad Request.
И больше ничего. Где-то через час решил убрать свою модель User и вернуть стандартную от Django. И о чудо, все заработало!
Можно ли как-то заставить
drf-simplejwt работать с собственной моделью User? Очень не хочу делать ForeignKey на другую таблицу, просто смысл JWT потеряется, опять запросы к бд пойдут.
Я откопал
djangorestframework-jwt-custom-user на просторах гугла, но либо это не то, либо я читать не умею и не понимаю, как надо использовать.