0

我正在使用 dj-rest-auth、allauth 和 simple jwt 来实现身份验证。

在 django-allauth 中,设置 ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION=True 将在验证电子邮件后自动登录用户。但是将密钥发布到“/dj-rest-auth/registration/verify-email/”仅返回 {“detail”:“ok”}。

下面的源代码解释了原因:

# 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,如何在验证后覆盖此视图以登录用户并返回访问代码?

4

2 回答 2

1

您应该使用该确认对象,编写confirmation.email_address一个 django-allauth EmailAddress 模型对象,然后获取用户(即您的用户模型)。总而言之,就是做confirmation.email_address.user。最后,从用户对象生成 JWT。

要生成正确的 JSON 响应,请实例化 LoginView 类,通过执行设置用户类属性,并通过执行LoginView().get_response()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获取 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 问题中发布了这个。所以希望这里发生的任何编辑也能落地。

于 2021-08-24T04:01:08.200 回答
1

我不得不处理完全相同的情况,对我来说似乎效果很好的是以下

  1. 创建一个客户电子邮件验证视图,而不是使用 dj_rest_auth 提供的视图。
  2. 从原始的VerifyEmailView自己的post方法中复制大部分代码
  3. 添加一行以获取 jwt 令牌 (self.access_token, self.refresh_token = jwt_encode(confirmation.email_address.user))
  4. 使用令牌响应

我的所有自定义视图看起来像这样

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)})
于 2021-10-20T09:59:53.010 回答