我在注册后通过电子邮件验证用户的代码有一个我无法查明的问题。成功注册后,用户会收到一封包含链接和令牌的电子邮件。然后,令牌将被验证为有效,或被标记为无效或过期。电子邮件已成功发送。然而,过期的和新的令牌也被标记为无效。我做错了什么?
这是我的 models.py 文件中的用户模型:
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=255, unique=True, db_index=True)
email = models.EmailField(max_length=255, unique=True, db_index=True)
is_verified = models.BooleanField(default=False)
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
这是我的serializers.py 文件:
from rest_framework import serializers
from .models import User
class RegisterSerializer(serializers.ModelSerializer):
password = serializers.CharField(max_length=68, min_length=8, write_only=True)
class Meta:
model = User
fields = ["email", "username", "password"]
def validate(self, attrs):
email = attrs.get("email", "")
username = attrs.get("username", "")
if not username.isalnum():
raise serializers.ValidationError(
"The username should only contain alphanumeric characters"
)
return attrs
def create(self, validated_data):
return User.objects.create_user(**validated_data)
class VerifyEmailSerializer(serializers.ModelSerializer):
token = serializers.CharField(max_length=555)
class Meta:
model = User
fields = ["token"]
views.py
import jwt
from django.conf import settings
from django.contrib.sites.shortcuts import get_current_site
from django.shortcuts import render
from django.urls import reverse
from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework import generics, status, views
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken
from .models import User
from .serializers import *
from .utils import Util
class RegisterView(generics.GenericAPIView):
serializer_class = RegisterSerializer
def post(self, request):
user = request.data
serializer = self.serializer_class(data=user)
serializer.is_valid(raise_exception=True)
serializer.save()
user_data = serializer.data
user = User.objects.get(email=user_data['email'])
token = RefreshToken.for_user(user).access_token
current_site = get_current_site(request).domain
relativeLink = reverse('email-verify')
absurl = 'http://'+current_site+relativeLink+"?token="+str(token)
email_body = 'Hi '+user.username + \
' Use the link below to verify your email \n' + absurl
data = {'email_body': email_body, 'to_email': user.email,
'email_subject': 'Verify your email'}
Util.send_email(data)
return Response(user_data, status=status.HTTP_201_CREATED)
class VerifyEmailView(views.APIView):
serializer_class = VerifyEmailSerializer
@extend_schema(
parameters=[
OpenApiParameter(
name="token", description="Description",
required=False, type=str, location=OpenApiParameter.QUERY
)])
def get(self, request):
token = request.GET.get('token')
try:
payload = jwt.decode(token, settings.SECRET_KEY)
user = User.objects.get(id=payload['user_id'])
if not user.is_verified:
user.is_verified = True
user.save()
return Response({'email': 'Successfully activated'}, status=status.HTTP_200_OK)
except jwt.ExpiredSignatureError as identifier:
return Response({'Error': 'Token Expired'}, status=status.HTTP_400_BAD_REQUEST)
except jwt.exceptions.DecodeError as identifier:
return Response({'Error': 'Invalid token'}, status=status.HTTP_400_BAD_REQUEST)
以及执行发送的文件(utils.py)
from django.core.mail import EmailMessage
class Util:
@staticmethod
def send_email(data):
email = EmailMessage(
subject=data["email_subject"], body=data["email_body"], to=[data["to_email"]])
email.send()
在
VerifyEmailView
中,您没有指定用于解码 JWT 的算法。
你的代码必须像这样更新 -
jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])