You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Djoser账户验证系统底层工作原理解析及自建验证系统时的UID与Token相关技术问题咨询

Great questions! Let's break this down step by step since I've worked with Djoser and built custom verification flows before.

Djoser Account Verification: Underlying Mechanics & Custom Implementation

1. How Djoser's Account Verification Works Under the Hood

Djoser is built on top of Django REST Framework (DRF) and leans heavily into Django's built-in auth system, so its verification flow is a structured extension of that:

  • Registration Submission: When a user sends their signup data (email, password, etc.), Djoser first validates the input against your configured rules (like password complexity, unique email). If valid, it creates a User instance with is_active=False (so the user can't log in yet).
  • Token & UID Generation: Next, it generates two key values:
    • UID: A base64-encoded version of the user's primary key (or a unique identifier for the user) – this lets the backend quickly look up the right user without exposing raw IDs directly.
    • Verification Token: A cryptographically signed token, not a JWT. It's generated using a token generator that combines user-specific data (like user ID, password hash, last login timestamp) with a timestamp to enforce expiration. Djoser uses a variant of Django's PasswordResetTokenGenerator for this.
  • Email Delivery: Djoser constructs a verification URL with the UID and Token, then sends it to the user's email via Django's email backend.
  • Verification Confirmation: When the user clicks the link, your frontend (or Djoser's default view) sends a POST request with UID and Token to the backend. Djoser decodes the UID to find the user, re-computes the expected token using the same generator, and checks if the submitted token matches and hasn't expired. If everything checks out, it sets user.is_active=True and completes the verification.

2. Verification Tokens: What They Are, How They Work, & Building a Custom Flow

What's the Verification Token? Is it JWT?

No, it's not a JWT. JWTs are designed for stateless authentication (carrying user claims) and can be reused until they expire. Djoser's verification token is a one-time, short-lived cryptographically signed token built specifically for account verification (or password resets). It's tied directly to the user's current state (like their password hash) – if the user changes their password before verifying, the old token becomes invalid automatically.

How the Token Works

The token is generated using HMAC-SHA256 encryption. The generator uses a combination of:

  • The user's unique ID
  • The user's password hash (so if the password changes, the token is no longer valid)
  • A timestamp (to set an expiration window, usually 1-2 days)
  • Optional user state (like is_active status)

When verifying, the backend re-calculates the token using the same inputs and compares it to the submitted token. If they match and the timestamp is within the expiration window, the token is valid.

Building a Custom Verification Flow (Without Djoser)

Let's walk through a Django/DRF-based implementation – the core logic translates to other frameworks too:

Step 1: Create a Custom Token Generator

First, make a token generator class (similar to Django's built-in one):

from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils import six

class AccountVerificationTokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        # Combine user data that changes when the user's state updates
        return (
            six.text_type(user.pk) + six.text_type(timestamp) +
            six.text_type(user.is_active) + six.text_type(user.password)
        )

account_verification_token = AccountVerificationTokenGenerator()

Step 2: Build the Registration View

Handle user signup, generate the token/UID, and send the verification email:

from django.core.mail import send_mail
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes
from rest_framework import generics, status
from rest_framework.response import Response
from .models import User
from .serializers import RegisterSerializer
from .tokens import account_verification_token

class RegisterView(generics.CreateAPIView):
    serializer_class = RegisterSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        user.is_active = False  # Deactivate until verification
        user.save()

        # Generate UID and Token
        uid = urlsafe_base64_encode(force_bytes(user.pk))
        token = account_verification_token.make_token(user)

        # Construct verification URL (replace with your frontend URL)
        verification_url = f"https://your-frontend.com/verify?uid={uid}&token={token}"

        # Send email
        send_mail(
            "Verify Your Account",
            f"Click the link to verify your account: {verification_url}",
            "no-reply@yourdomain.com",
            [user.email],
            fail_silently=False,
        )

        return Response(
            {"message": "Registration successful. Check your email for verification link."},
            status=status.HTTP_201_CREATED
        )

Step 3: Build the Verification View

Validate the UID and Token, then activate the user:

from django.utils.http import urlsafe_base64_decode
from django.utils.encoding import force_str
from rest_framework import generics, status
from rest_framework.response import Response
from .models import User
from .tokens import account_verification_token

class VerifyAccountView(generics.GenericAPIView):
    def post(self, request, *args, **kwargs):
        uid = request.data.get("uid")
        token = request.data.get("token")

        try:
            # Decode UID to get user ID
            user_id = force_str(urlsafe_base64_decode(uid))
            user = User.objects.get(pk=user_id)
        except (TypeError, ValueError, OverflowError, User.DoesNotExist):
            return Response({"error": "Invalid UID"}, status=status.HTTP_400_BAD_REQUEST)

        # Verify token
        if account_verification_token.check_token(user, token):
            user.is_active = True
            user.save()
            return Response({"message": "Account verified successfully"}, status=status.HTTP_200_OK)
        else:
            return Response({"error": "Invalid or expired token"}, status=status.HTTP_400_BAD_REQUEST)

Step 4: Frontend Handling

  • When the user clicks the verification link, parse the uid and token from the URL parameters.
  • Render a simple page with a "Verify Account" button (or auto-submit a POST request to your verification endpoint with the UID and Token).
  • Display success/error messages based on the backend response.

内容的提问来源于stack exchange,提问作者Melly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 14:24:07