简体   繁体   English

dj-rest-auth:ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION 不工作

[英]dj-rest-auth: ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION not working

I'm using dj-rest-auth, allauth, and simple jwt to implement authentication.我正在使用 dj-rest-auth、allauth 和简单的 jwt 来实现身份验证。

In django-allauth, setting ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION=True will automatically login user after the email is verified.在 django-allauth 中,设置 ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION=True 将在验证 email 后自动登录用户。 But posting key to "/dj-rest-auth/registration/verify-email/" only returns {"detail":"ok"}.但是将密钥发布到“/dj-rest-auth/registration/verify-email/”只会返回 {"detail":"ok"}。

The source code below explains why:下面的源代码解释了原因:

# 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)

Since I'm using JWT, how could I override this view to login user after verification and return access code?由于我使用的是 JWT,如何在验证后覆盖此视图以登录用户并返回访问代码?

You should take that confirmation object, write confirmation.email_address which is a django-allauth EmailAddress model object, then get the user (ie your User model).您应该获取该确认对象,编写confirmation.email_address ,这是一个django-allauth EmailAddress 模型对象,然后获取用户(即您的用户模型)。 All in all, just do confirmation.email_address.user .总而言之,只需执行confirmation.email_address.user Finally, generate a JWT from the user object.最后,从用户对象生成 JWT。

To generate the proper JSON response, instantiate the LoginView class, set the user class attribute by doing 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要生成正确的 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设置用户类属性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 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 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 , and grab Response object by doing 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 ,并通过执行LoginView().get_response()获取 Response 对象

Make sure you check for all edge cases like if email address does not exist etc.确保检查所有边缘情况,例如电子邮件地址是否不存在等。

All in all:总而言之:

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()

Let us know if that works!让我们知道这是否有效!

References:参考:

I've posted this in your GitHub issue as well.我也在你的 GitHub 问题中发布了这个。 So hopefully whatever edits happen here also land there too.所以希望这里发生的任何编辑也会在那里发生。

I had to deal with the exact same case and what seems to work quite well for me is the following我不得不处理完全相同的情况,对我来说似乎工作得很好的是以下内容

  1. Create a custome email verify view instead of use the provided one from the dj_rest_auth.创建客户电子邮件验证视图,而不是使用 dj_rest_auth 中提供的视图。
  2. Copy most of the code from the original VerifyEmailView's own post method复制原VerifyEmailView自带的post方法的大部分代码
  3. add a line to get jwt tokens (self.access_token, self.refresh_token = jwt_encode(confirmation.email_address.user))添加一行以获取 jwt 令牌 (self.access_token, self.refresh_token = jwt_encode(confirmation.email_address.user))
  4. Response with tokens用令牌响应

all and all my Custom view looks like this我所有的自定义视图看起来像这样

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)})

I got the following working based on a combination of ideas from both of the above two answers and comments on the github issue :基于以上两个答案的想法和对github 问题的评论,我得到了以下工作:

from dj_rest_auth.utils import jwt_encode
from dj_rest_auth.registration.views import VerifyEmailView, LoginView

from dj_rest_auth.registration import views

class CustomVerifyEmailView(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)

        login_view = LoginView()

        self.user = 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:
            #you'll have to figure this out if you need it. I didn't.
            raise NotImplementedError 


        data = {
            'user': self.user,
            'access_token': self.access_token,
            'refresh_token': self.refresh_token
            }

        login_response_serializer = login_view.get_response_serializer()
        login_serializer = login_response_serializer(instance=data)

        return Response(login_serializer.data, status=status.HTTP_200_OK)
        

views.VerifyEmailView = CustomVerifyEmailView

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM