> 백엔드 개발 > 파이썬 튜토리얼 > drf 프로젝트에서 전화번호 확인 구현

drf 프로젝트에서 전화번호 확인 구현

Mary-Kate Olsen
풀어 주다: 2024-12-28 10:17:10
원래의
203명이 탐색했습니다.

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

Django REST Framework(DRF)로 전화번호 인증 시스템을 구현하려면 다음 단계를 따르세요. 이 시스템을 통해 사용자는 전화번호를 제공하고, SMS(예: Twilio를 통해)로 확인 코드를 받고, 이 코드를 확인하여 번호를 확인할 수 있습니다.

주요 단계:

  1. 필요한 종속성 설치
  2. 전화번호를 포함하도록 사용자 템플릿 편집
  3. 인증 코드를 저장할 템플릿 만들기
  4. SMS 전송 서비스 구성(예: Twilio)
  5. DRF 시리얼라이저 생성
  6. 뷰 및 API 경로 생성
  7. 검증 로직 및 보안 관리

1. 필요한 종속성 설치

먼저 필요한 라이브러리를 설치했는지 확인하세요.

  • Django REST 프레임워크: 아직 하지 않으셨다면
  • Twilio: SMS 전송용.
  • django-phonenumber-field: 전화번호를 확인하고 형식을 지정합니다.

pip를 통해 설치:

1

pip install djangorestframework twilio django-phonenumber-field

로그인 후 복사
로그인 후 복사

settings.py의 INSTALLED_APPS에 Phonenumber_field 및 Rest_framework를 추가하세요.

1

2

3

4

5

6

7

8

# settings.py

 

INSTALLED_APPS = [

    # ...

    'rest_framework',

    'phonenumber_field',

    # ...

]

로그인 후 복사
로그인 후 복사

2. 전화번호를 포함하도록 사용자 템플릿을 변경합니다.

맞춤 사용자 템플릿을 사용하는 경우 전화번호 및 확인 플래그 필드를 추가하세요.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

# 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

로그인 후 복사
로그인 후 복사

참고: 이미 사용자 모델이 있는 경우에는 Phone_number 및 is_phone_verified 필드를 적절하게 추가해야 합니다.

3. 인증 코드를 저장할 템플릿 만들기

이 템플릿은 사용자에게 전송된 인증 코드를 저장합니다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

# 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'}"

로그인 후 복사
로그인 후 복사

4. SMS 전송 서비스 구성(예: Twilio)

Twilio를 사용하여 문자 메시지를 보낼 수 있습니다. 먼저 Twilio 계정을 만들고 필요한 자격 증명(ACCOUNT_SID, AUTH_TOKEN, FROM_NUMBER)을 획득하세요.

settings.py에 다음 구성을 추가하세요.

1

2

3

4

5

# settings.py

 

TWILIO_ACCOUNT_SID = 'votre_account_sid'

TWILIO_AUTH_TOKEN = 'votre_auth_token'

TWILIO_FROM_NUMBER = '+1234567890'  # Numéro Twilio

로그인 후 복사
로그인 후 복사

SMS 전송을 관리하기 위한 utils.py 파일 만들기:

1

2

3

4

5

6

7

8

9

10

11

12

13

# 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

로그인 후 복사
로그인 후 복사

5. DRF 직렬 변환기 생성

확인 요청 및 코드 유효성 검사를 처리하기 위한 직렬 변환기를 만듭니다.

1

pip install djangorestframework twilio django-phonenumber-field

로그인 후 복사
로그인 후 복사

6. API 보기 및 경로 생성

확인 요청 및 코드 유효성 검사를 관리하기 위한 뷰를 만듭니다.

1

2

3

4

5

6

7

8

# settings.py

 

INSTALLED_APPS = [

    # ...

    'rest_framework',

    'phonenumber_field',

    # ...

]

로그인 후 복사
로그인 후 복사

참고: 확인 중에 사용자를 생성하거나 기존 사용자를 다르게 관리하려는 경우 등 필요에 따라 이러한 보기를 조정할 수 있습니다.

7. API 경로 구성

urls.py에 해당 경로를 추가하세요.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

# 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

로그인 후 복사
로그인 후 복사

8. 추가 로직 추가(선택 사항)

가지다. 사용자별 고유 코드 생성

요청 보기를 편집하여 코드를 특정 사용자와 연결하거나 새 사용자를 생성하세요.

비. 요청 수 제한

악용을 방지하려면 사용자 또는 전화번호당 인증 요청 수를 제한하세요.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

# 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'}"

로그인 후 복사
로그인 후 복사

기음. 검증 중 사용자 관리

인증 후 사용자를 생성하거나 해당 번호를 기존 사용자와 연결할 수 있습니다.

9. 테스트 및 검증

시스템을 프로덕션 환경에 배포하기 전에 개발 환경에서 테스트해 보시기 바랍니다. 다음 사항을 확인하세요.

  • SMS 메시지가 올바르게 전송되었습니다.
  • 코드가 생성되어 안전하게 저장됩니다.
  • 설정된 시간이 지나면 수표가 만료됩니다.
  • 오류가 올바르게 처리되고 사용자에게 전달됩니다.

완전한 구현 예

개요를 설명하기 위해 영향을 받는 파일의 전체 예는 다음과 같습니다.

models.py

1

2

3

4

5

# settings.py

 

TWILIO_ACCOUNT_SID = 'votre_account_sid'

TWILIO_AUTH_TOKEN = 'votre_auth_token'

TWILIO_FROM_NUMBER = '+1234567890'  # Numéro Twilio

로그인 후 복사
로그인 후 복사

serializers.py

1

2

3

4

5

6

7

8

9

10

11

12

13

# 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

로그인 후 복사
로그인 후 복사

views.py

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

# 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

로그인 후 복사

urls.py

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

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

로그인 후 복사

utils.py

1

2

3

4

5

6

7

8

9

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

]

로그인 후 복사

10. 보안 및 최적화

  • 확인 시도 제한: 무차별 대입 공격을 방지하기 위해 확인 시도 횟수를 제한하는 시스템을 구현합니다.

  • 코드 암호화: 보안 강화를 위해 데이터베이스의 확인 코드를 암호화할 수 있습니다.

  • 비동기 작업 사용: 성능을 향상하려면 비동기 작업(예: Celery 사용)을 사용하여 API 요청을 차단하지 않고 SMS를 보내세요.

  • HTTPS 구성: 보안 통신을 위해 HTTPS를 통해 API에 액세스할 수 있는지 확인하세요.

위 내용은 drf 프로젝트에서 전화번호 확인 구현의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿