Heim > Backend-Entwicklung > Python-Tutorial > Implementierung der Telefonnummernüberprüfung in einem DRF-Projekt

Implementierung der Telefonnummernüberprüfung in einem DRF-Projekt

Mary-Kate Olsen
Freigeben: 2024-12-28 10:17:10
Original
135 Leute haben es durchsucht

Implémentation de vérification de numéro de téléphone dans un projet drf

Um ein Telefonnummernüberprüfungssystem mit Django REST Framework (DRF) zu implementieren, können Sie die folgenden Schritte ausführen. Dieses System ermöglicht es Benutzern, ihre Telefonnummer anzugeben, einen Bestätigungscode per SMS zu erhalten (z. B. über Twilio) und diesen Code zu validieren, um ihre Nummer zu bestätigen.

Hauptschritte:

  1. Notwendige Abhängigkeiten installieren
  2. Benutzervorlage bearbeiten, um Telefonnummer einzuschließen
  3. Erstellen Sie eine Vorlage zum Speichern von Bestätigungscodes
  4. Konfigurieren Sie einen SMS-Versanddienst (z. B. Twilio)
  5. DRF-Serialisierer erstellen
  6. Ansichten und API-Routen erstellen
  7. Verifizierungslogik und Sicherheit verwalten

1. Installieren Sie die erforderlichen Abhängigkeiten

Stellen Sie zunächst sicher, dass Sie die erforderlichen Bibliotheken installiert haben:

  • Django REST Framework: Falls Sie es noch nicht getan haben.
  • Twilio: Zum Senden von SMS.
  • django-phonenumber-field: Zur Validierung und Formatierung von Telefonnummern.

Installieren Sie sie über pip:

pip install djangorestframework twilio django-phonenumber-field
Nach dem Login kopieren
Nach dem Login kopieren

Fügen Sie phonenumber_field und rest_framework zu Ihren INSTALLED_APPS in Settings.py hinzu:

# settings.py

INSTALLED_APPS = [
    # ...
    'rest_framework',
    'phonenumber_field',
    # ...
]
Nach dem Login kopieren
Nach dem Login kopieren

2. Ändern Sie die Benutzervorlage so, dass sie die Telefonnummer einschließt

Wenn Sie eine benutzerdefinierte Benutzervorlage verwenden, fügen Sie ein Feld für die Telefonnummer und ein Verifizierungskennzeichen hinzu.

# models.py

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
from phonenumber_field.modelfields import PhoneNumberField

class UserManager(BaseUserManager):
    def create_user(self, email, username, phone_number, password=None):
        if not email:
            raise ValueError('Les utilisateurs doivent avoir une adresse email')
        if not phone_number:
            raise ValueError('Les utilisateurs doivent avoir un numéro de téléphone')

        user = self.model(
            email=self.normalize_email(email),
            username=username,
            phone_number=phone_number,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, username, phone_number, password=None):
        user = self.create_user(
            email,
            username,
            phone_number,
            password=password,
        )
        user.is_admin = True
        user.save(using=self._db)
        return user

class CustomUser(AbstractBaseUser):
    email = models.EmailField(verbose_name='adresse email', max_length=255, unique=True)
    username = models.CharField(max_length=50, unique=True)
    phone_number = PhoneNumberField(unique=True, null=False, blank=False)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    is_phone_verified = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username', 'phone_number']

    def __str__(self):
        return self.email

    @property
    def is_staff(self):
        return self.is_admin
Nach dem Login kopieren
Nach dem Login kopieren

Hinweis: Wenn Sie bereits über ein Benutzermodell verfügen, stellen Sie sicher, dass Sie die Felder „phone_number“ und „is_phone_verified“ entsprechend hinzufügen.

3. Erstellen Sie eine Vorlage zum Speichern von Bestätigungscodes

In dieser Vorlage werden an Benutzer gesendete Bestätigungscodes gespeichert.

# models.py

import random
import string
from django.utils import timezone
from datetime import timedelta

class PhoneVerification(models.Model):
    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='phone_verifications')
    code = models.CharField(max_length=6)
    created_at = models.DateTimeField(auto_now_add=True)
    is_verified = models.BooleanField(default=False)

    def is_expired(self):
        return self.created_at < timezone.now() - timedelta(minutes=10)  # Expire après 10 minutes

    def __str__(self):
        return f"Vérification de {self.user.email} - {'Validé' if self.is_verified else 'En attente'}"
Nach dem Login kopieren
Nach dem Login kopieren

4. Konfigurieren Sie einen SMS-Versanddienst (z. B. Twilio).

Sie können Twilio zum Senden von Textnachrichten verwenden. Erstellen Sie zunächst ein Twilio-Konto und besorgen Sie sich die erforderlichen Anmeldeinformationen (ACCOUNT_SID, AUTH_TOKEN, FROM_NUMBER).

Fügen Sie diese Konfigurationen zu Ihrer Settings.py hinzu:

# settings.py

TWILIO_ACCOUNT_SID = 'votre_account_sid'
TWILIO_AUTH_TOKEN = 'votre_auth_token'
TWILIO_FROM_NUMBER = '+1234567890'  # Numéro Twilio
Nach dem Login kopieren
Nach dem Login kopieren

Erstellen Sie eine utils.py-Datei, um den SMS-Versand zu verwalten:

# utils.py

from django.conf import settings
from twilio.rest import Client

def send_sms(to, message):
    client = Client(settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN)
    message = client.messages.create(
        body=message,
        from_=settings.TWILIO_FROM_NUMBER,
        to=str(to)
    )
    return message.sid
Nach dem Login kopieren
Nach dem Login kopieren

5. Erstellen Sie DRF-Serialisierer

Erstellen Sie Serialisierer, um die Verifizierungsanfrage und Codevalidierung zu verarbeiten.

pip install djangorestframework twilio django-phonenumber-field
Nach dem Login kopieren
Nach dem Login kopieren

6. Erstellen Sie API-Ansichten und Routen

Erstellen Sie Ansichten, um Verifizierungsanfragen und Codevalidierung zu verwalten.

# settings.py

INSTALLED_APPS = [
    # ...
    'rest_framework',
    'phonenumber_field',
    # ...
]
Nach dem Login kopieren
Nach dem Login kopieren

Hinweis: Möglicherweise möchten Sie diese Ansichten nach Bedarf anpassen, beispielsweise wenn Sie während der Überprüfung einen Benutzer erstellen oder vorhandene Benutzer anders verwalten möchten.

7. Konfigurieren Sie API-Routen

Fügen Sie die entsprechenden Routen in Ihre urls.py ein.

# models.py

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
from phonenumber_field.modelfields import PhoneNumberField

class UserManager(BaseUserManager):
    def create_user(self, email, username, phone_number, password=None):
        if not email:
            raise ValueError('Les utilisateurs doivent avoir une adresse email')
        if not phone_number:
            raise ValueError('Les utilisateurs doivent avoir un numéro de téléphone')

        user = self.model(
            email=self.normalize_email(email),
            username=username,
            phone_number=phone_number,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, username, phone_number, password=None):
        user = self.create_user(
            email,
            username,
            phone_number,
            password=password,
        )
        user.is_admin = True
        user.save(using=self._db)
        return user

class CustomUser(AbstractBaseUser):
    email = models.EmailField(verbose_name='adresse email', max_length=255, unique=True)
    username = models.CharField(max_length=50, unique=True)
    phone_number = PhoneNumberField(unique=True, null=False, blank=False)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    is_phone_verified = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username', 'phone_number']

    def __str__(self):
        return self.email

    @property
    def is_staff(self):
        return self.is_admin
Nach dem Login kopieren
Nach dem Login kopieren

8. Zusätzliche Logiken hinzufügen (optional)

hat. Generierung von eindeutigem Code pro Benutzer

Bearbeiten Sie die Anforderungsansicht, um den Code einem bestimmten Benutzer zuzuordnen oder einen neuen Benutzer zu erstellen.

B. Begrenzen Sie die Anzahl der Anfragen

Um Missbrauch zu vermeiden, begrenzen Sie die Anzahl der Verifizierungsanfragen pro Benutzer oder Telefonnummer.

# models.py

import random
import string
from django.utils import timezone
from datetime import timedelta

class PhoneVerification(models.Model):
    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='phone_verifications')
    code = models.CharField(max_length=6)
    created_at = models.DateTimeField(auto_now_add=True)
    is_verified = models.BooleanField(default=False)

    def is_expired(self):
        return self.created_at < timezone.now() - timedelta(minutes=10)  # Expire après 10 minutes

    def __str__(self):
        return f"Vérification de {self.user.email} - {'Validé' if self.is_verified else 'En attente'}"
Nach dem Login kopieren
Nach dem Login kopieren

C. Benutzerverwaltung während der Verifizierung

Sie können nach der Überprüfung entscheiden, einen Benutzer zu erstellen oder die Nummer einem vorhandenen Benutzer zuzuordnen.

9. Tests und Validierung

Testen Sie Ihr System unbedingt in einer Entwicklungsumgebung, bevor Sie es in der Produktion bereitstellen. Überprüfen Sie Folgendes:

  • SMS-Nachrichten werden korrekt gesendet.
  • Codes werden sicher generiert und gespeichert.
  • Schecks verfallen nach der eingestellten Zeit.
  • Fehler werden korrekt behandelt und dem Benutzer mitgeteilt.

Vollständiges Implementierungsbeispiel

Um Ihnen einen Überblick zu geben, finden Sie hier ein vollständiges Beispiel der betroffenen Dateien.

models.py

# settings.py

TWILIO_ACCOUNT_SID = 'votre_account_sid'
TWILIO_AUTH_TOKEN = 'votre_auth_token'
TWILIO_FROM_NUMBER = '+1234567890'  # Numéro Twilio
Nach dem Login kopieren
Nach dem Login kopieren

serializers.py

# utils.py

from django.conf import settings
from twilio.rest import Client

def send_sms(to, message):
    client = Client(settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN)
    message = client.messages.create(
        body=message,
        from_=settings.TWILIO_FROM_NUMBER,
        to=str(to)
    )
    return message.sid
Nach dem Login kopieren
Nach dem Login kopieren

Ansichten.py

# serializers.py

from rest_framework import serializers
from .models import CustomUser, PhoneVerification
from phonenumber_field.serializerfields import PhoneNumberField

class PhoneVerificationRequestSerializer(serializers.Serializer):
    phone_number = PhoneNumberField()

    def validate_phone_number(self, value):
        if CustomUser.objects.filter(phone_number=value).exists():
            raise serializers.ValidationError("Ce numéro de téléphone est déjà utilisé.")
        return value

class PhoneVerificationCodeSerializer(serializers.Serializer):
    phone_number = PhoneNumberField()
    code = serializers.CharField(max_length=6)

    def validate(self, data):
        phone_number = data.get('phone_number')
        code = data.get('code')

        try:
            user = CustomUser.objects.get(phone_number=phone_number)
        except CustomUser.DoesNotExist:
            raise serializers.ValidationError("Utilisateur non trouvé avec ce numéro de téléphone.")

        try:
            verification = PhoneVerification.objects.filter(user=user, code=code, is_verified=False).latest('created_at')
        except PhoneVerification.DoesNotExist:
            raise serializers.ValidationError("Code de vérification invalide.")

        if verification.is_expired():
            raise serializers.ValidationError("Le code de vérification a expiré.")

        data['user'] = user
        data['verification'] = verification
        return data
Nach dem Login kopieren

urls.py

# views.py

from rest_framework import generics, status
from rest_framework.response import Response
from .serializers import PhoneVerificationRequestSerializer, PhoneVerificationCodeSerializer
from .models import CustomUser, PhoneVerification
from .utils import send_sms
import random
import string
from django.utils import timezone
from rest_framework.permissions import AllowAny

class PhoneVerificationRequestView(generics.GenericAPIView):
    serializer_class = PhoneVerificationRequestSerializer
    permission_classes = [AllowAny]

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        phone_number = serializer.validated_data['phone_number']

        # Générer un code de 6 chiffres
        code = ''.join(random.choices(string.digits, k=6))

        try:
            user = CustomUser.objects.get(phone_number=phone_number)
            # Si l'utilisateur existe déjà, ne pas permettre la création d'un nouveau
            return Response({"detail": "Ce numéro de téléphone est déjà associé à un utilisateur."}, status=status.HTTP_400_BAD_REQUEST)
        except CustomUser.DoesNotExist:
            pass  # Permettre la création si nécessaire

        # Créer une instance de PhoneVerification
        verification = PhoneVerification.objects.create(user=None, code=code)  # user=None pour l'instant

        # Envoyer le code par SMS
        try:
            send_sms(phone_number, f"Votre code de vérification est : {code}")
        except Exception as e:
            return Response({"detail": "Erreur lors de l'envoi du SMS."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        return Response({"detail": "Code de vérification envoyé."}, status=status.HTTP_200_OK)

class PhoneVerificationCodeView(generics.GenericAPIView):
    serializer_class = PhoneVerificationCodeSerializer
    permission_classes = [AllowAny]

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        verification = serializer.validated_data['verification']

        # Marquer la vérification comme validée
        verification.is_verified = True
        verification.save()

        # Mettre à jour l'utilisateur
        user.is_phone_verified = True
        user.save()

        return Response({"detail": "Numéro de téléphone vérifié avec succès."}, status=status.HTTP_200_OK)
Nach dem Login kopieren

utils.py

# urls.py

from django.urls import path
from .views import PhoneVerificationRequestView, PhoneVerificationCodeView

urlpatterns = [
    path('api/verify-phone/request/', PhoneVerificationRequestView.as_view(), name='phone-verification-request'),
    path('api/verify-phone/verify/', PhoneVerificationCodeView.as_view(), name='phone-verification-verify'),
]
Nach dem Login kopieren

10. Sichern und optimieren

  • Überprüfungsversuche begrenzen: Implementieren Sie ein System, um die Anzahl der Überprüfungsversuche zu begrenzen, um Brute-Force-Angriffe zu vermeiden.

  • Codes verschlüsseln: Für zusätzliche Sicherheit können Sie die Bestätigungscodes in der Datenbank verschlüsseln.

  • Asynchrone Aufgaben verwenden: Um die Leistung zu verbessern, verwenden Sie asynchrone Aufgaben (z. B. mit Celery), um SMS zu senden, ohne API-Anfragen zu blockieren.

  • HTTPS konfigurieren: Stellen Sie sicher, dass Ihre API über HTTPS zugänglich ist, um die Kommunikation zu sichern.

Das obige ist der detaillierte Inhalt vonImplementierung der Telefonnummernüberprüfung in einem DRF-Projekt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage