#django #django-rest-auth #dj-rest-auth
Вопрос:
Я использую dj-rest-auth, allauth и simple jwt для реализации аутентификации.
В django-allauth установка ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION=True автоматически приведет к входу пользователя в систему после подтверждения электронной почты. Но отправка ключа в «/dj-rest-auth/регистрация/проверка электронной почты/» возвращает только {«подробности»:»ок»}.
В приведенном ниже исходном коде объясняется, почему:
# allauth
class ConfirmEmailView(TemplateResponseMixin, LogoutFunctionalityMixin, View):
# ...
def post(self, *args, **kwargs):
# ...
if app_settings.LOGIN_ON_EMAIL_CONFIRMATION:
resp = self.login_on_confirm(confirmation)
if resp is not None:
return resp # this is a HttpResponseRedirect object
# ...
# dj-rest-auth
class VerifyEmailView(APIView, ConfirmEmailView):
# ...
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.kwargs['key'] = serializer.validated_data['key']
confirmation = self.get_object()
confirmation.confirm(self.request)
return Response({'detail': _('ok')}, status=status.HTTP_200_OK)
Поскольку я использую JWT, как я могу переопределить это представление для входа пользователя в систему после проверки и возврата кода доступа?
Ответ №1:
Вы должны взять этот объект подтверждения, написать confirmation.email_address
, который является объектом модели адреса электронной почты django-allauth, а затем получить пользователя (т. Е. вашу модель пользователя). В общем, просто делай confirmation.email_address.user
. Наконец, создайте JWT из объекта пользователя.
Чтобы сгенерировать правильный ответ JSON, создайте экземпляр класса LoginView, установите атрибут класса пользователя , выполнив view = LoginView(); view.user = confirmation.email_address.user; # TODO do view.login() but you need to customize it so that you don't call user
, и захватите объект ответа, выполнив LoginView().get_response()
Убедитесь, что вы проверяете все крайние случаи, например, если адрес электронной почты не существует и т. Д.
В целом:
class CustomVerifyEmailView(VerifyEmailView):
# ...
def post(self, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.kwargs['key'] = serializer.validated_data['key']
confirmation = self.get_object()
confirmation.confirm(self.request)
login_view = LoginView()
login_view.user = confirmation.email_address.user
if getattr(settings, 'REST_USE_JWT', False):
self.access_token, self.refresh_token = jwt_encode(self.user)
else:
self.token = create_token(
self.token_model, self.user,
self.serializer,
)
if getattr(settings, 'REST_SESSION_LOGIN', True):
self.process_login()
return login_view.get_response()
Дайте нам знать, если это сработает!
Рекомендации:
Я также опубликовал это в вашем выпуске GitHub. Так что, надеюсь, какие бы изменения ни происходили здесь, они также окажутся и там.
Ответ №2:
Мне пришлось иметь дело с точно таким же случаем, и то, что, кажется, очень хорошо работает для меня, заключается в следующем
- Создайте представление проверки электронной почты custome вместо использования предоставленного представления из dj_rest_auth.
- Скопируйте большую часть кода из собственного метода post исходного файла VerifyEmailView
- добавьте строку для получения токенов jwt (self.access_token, self.refresh_token = jwt_encode(подтверждение.адрес электронной почты.пользователь))
- Ответ с помощью токенов
все и все мое пользовательское представление выглядит так
from dj_rest_auth.utils import jwt_encode
from dj_rest_auth.registration.views import VerifyEmailView
class CustomeVerifyEmailView(VerifyEmailView):
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.kwargs['key'] = serializer.validated_data['key']
confirmation = self.get_object()
confirmation.confirm(self.request)
self.access_token, self.refresh_token = jwt_encode(confirmation.email_address.user)
return Response({"refresh": str(self.refresh_token), "access": str(self.access_token)})