通过从忘记密码中检索Email重置密码查看django

k0pti3hp  于 2023-06-25  发布在  Go
关注(0)|答案(1)|浏览(237)

在下面的代码中,当“忘记密码”运行时,它会从用户处获取“电子邮件”输入并生成令牌,使用该电子邮件和令牌,用户可以更改其密码,但我想要的是:用户只需要输入“new_password”和“reconfirm_password”而不是电子邮件来更改密码,电子邮件应该从“忘记密码视图”中获取,以下代码在执行时会出现此错误:无法访问与值不关联的局部变量“email”
views.py

class ChangePasswordView(APIView):
    def get(self, request, token, email):
        context = {}
        try:
            profile_obj = UserAccount.objects.filter(
                forget_password_token=token).first()
            if profile_obj:
                context['email'] = email
            else:
                return JsonResponse({'message': 'Invalid token.'})
        except Exception as e:
            print(e)
            return JsonResponse({'message': 'An error occurred.'})

        return JsonResponse(context)

    def post(self, request, **kwargs):
        try:
            context = {}
            profile_obj = UserAccount.objects.filter(
                email=email).first()
            if profile_obj:
                context['email'] = email
            new_password = request.data.get('new_password')
            confirm_password = request.data.get('reconfirm_password')
            email = request.data.get('email') 

            print(new_password)

            if email is None:
                return JsonResponse({'message': 'No user email found.'})

            if new_password != confirm_password:
                return JsonResponse({'message': 'Both passwords should be equal.'})

            user_obj = UserAccount.objects.get(email=email)
            user_obj.set_password(new_password)
            user_obj.save()
            return JsonResponse({'message': 'Password changed successfully.'})

        except Exception as e:
            print(e)
            return JsonResponse({'message': 'An error occurred.'})

@method_decorator(csrf_exempt, name='dispatch')
class ForgetPasswordView(View):
    def post(self, request):
        try:
            data = json.loads(request.body)
            email = data.get('email')
            if not UserAccount.objects.filter(email=email).exists():
                return JsonResponse({'message': 'No user found with this email.'})

            user_obj = UserAccount.objects.get(email=email)
            token = str(uuid.uuid4())
            user_obj.forget_password_token = token
            user_obj.save()
            send_forget_password_mail(user_obj.email, token)
            return JsonResponse({'message': 'An email has been sent.'})

        except Exception as e:
            print(e)
            return JsonResponse({'message': 'An error occurred.'})

        return JsonResponse({'message': 'Something went wrong.'})
dxxyhpgq

dxxyhpgq1#

我个人使用rest_framework_simplejwt生成一个令牌,并发送一封带有URL和令牌的电子邮件到忘记密码请求的电子邮件。然后在新的URL上提交新密码并解码令牌以获取用户并更改密码。

用户模型

在这里,您可以访问刷新和访问令牌,但我们需要的是访问令牌。

from django.db import models
from django.contrib.auth.models import (
    AbstractBaseUser, BaseUserManager, PermissionsMixin)
from rest_framework_simplejwt.tokens import RefreshToken
import uuid

class User(AbstractBaseUser, PermissionsMixin):
    public_id = models.CharField(
        max_length=255, default=uuid.uuid4, editable=False, unique=True)
    username = models.CharField(max_length=60, unique=True)
    email = models.EmailField(max_length=50, unique=True)
    firstname = models.CharField(max_length=250, null=False)
    lastname= models.CharField(max_length=250, null=False)
    password = models.CharField(max_length=250, null=False)
    is_superuser = models.BooleanField(default=False)
    is_verified = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    last_login = models.DateTimeField(null=True)
    created_at = models.DateTimeField(auto_now_add=True, null=False)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username', 'firstname', 'lastname']

    def __str__(self):
        return self.username+'( '+self.email+' )'

    def tokens(self):
        refresh = RefreshToken.for_user(self)
        return {
            'refresh': str(refresh),
            'access': str(refresh.access_token)
        }

    class Meta:
        db_table = 'users'
        ordering = ('-id',)

忘记密码查看

您可以将**localhost:8000/set-password/**替换为设置密码端点的反向URL。找到用户后,将生成令牌并将其发送到用户的电子邮件。

class RequestPasswordResetEmail(generics.GenericAPIView):
    serializer_class = ResetPasswordEmailRequestSerializer

    def post(self, request,  *args, **kwargs):
        try:
            user = User.objects.get(email=request.data['email'])
            token = RefreshToken.for_user(user).access_token
            absurl = "localhost:8000/set-password/?token="+str(token)
            htmly = get_template('emailTemplates/forgotPassword.html')
            context = {'firstname': user.firstname,
                       "absurl": absurl}
            html_content = htmly.render(context)
            msg = EmailMessage(subject='Password Reset', body=html_content,
                               to=[user.email],
                               from_email=os.environ['EMAIL_SEND_AS'])
            msg.content_subtype = "html"
            msg.send()
            data = {'status': status.HTTP_200_OK, 'msg': 'Email Sent.'}
        except User.DoesNotExist:
            data = {'status': status.HTTP_200_OK, 'msg': 'Email Sent.'}
        return HttpResponse(json.dumps(data))

设置密码视图

对令牌进行解码以获得更改的用户ID和用户密码,否则给出正确的响应。

class SetAccountPasswordAPIView(generics.RetrieveAPIView):
    serializer_class = EmailVerificationSerializer

    def get(self, request):
        token = request.GET.get('token')
        try:
            payload = jwt.decode(
                token, settings.SECRET_KEY, algorithms='HS256')
            user = User.objects.get(id=payload['user_id'])
            user.set_password(request.data['password'])
            user.save()
            return Response({'message': 'Password Set Successfully'},
                                status=status.HTTP_200_OK)
        except jwt.ExpiredSignatureError:
            return Response({'message': 'Token Has Expired'},
                            status=status.HTTP_400_BAD_REQUEST)
        except jwt.exceptions.DecodeError:
            return Response({'message': 'Invalid Token'},
                            status=status.HTTP_400_BAD_REQUEST)

相关问题