본문 바로가기
STUDY/CS

복습(환경변수 설정, 이메일 인증)

by 수쨔앙 2023. 1. 5.

django environ 사용한 환경변수 설정하기

 

1. django-environ 설치

pip install django-environ

 

2. .env 생성

민감한 데이터를 관리할 .env 파일 생성

 

3. .env 파일에 변수 넣기

SECRET_KEY='django-insecur어쩌구저쩌구~~=nfci4(&9+tai*'
DEBUG=1
SECRET_EMAIL="아이디@gmail.com"
SECRET_PASSWORD="앱비밀번호"

이때 변수와 값 사이에 공백이 없어야한다.

'='다음에 괜히 띄어쓰기 하지 말자 띄어쓰기하면 에러난다

 

4. settings.py에 적용하기

import os
import environ
from pathlib import Path
from datetime import timedelta

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

env = environ.Env(DEBUG=(bool, True))
environ.Env.read_env(
    env_file=os.path.join(BASE_DIR, '.env')
)

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/


# secret_key와 debug에 넣은 값들을 불러올 수 있게 설정
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get('SECRET_KEY',"")

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.environ.get('DEBUG','0') == '1'

os.environ.get의 두번째 인자는 존재하지 않을 경우 예외처리를 해주는 것이다.

 

 


이메일 인증

 

1. SMTP 

2. 이메일 전송

3. uid, token

4. 메일 인증

 

1.SMTP

SMTP를 사용하였고

drf 를 이용하여 이메일 인증 코드를 작성하였다.

 

2. 이메일 전송

유저가 생성(회원가입) 될 때 이메일 인증 메일이 전송되어야 하기 때문에

serializer의 user를 생성하는 create에서 이메일을 전송하는 코드를 작성했다.

 

message = render_to_string('email_valid.html', {
            'user': user,
            'domain': 'http://127.0.0.1:8000',
            'uid': urlsafe_base64_encode(force_bytes(user.pk)),
            'token': account_activation_token.make_token(user),
        })
        plain_message = strip_tags(message)
        mail_subject = "MMOP 이메일 인증 링크 보내드립니다"
        to_email = user.email
        mail.send_mail(mail_subject, plain_message, settings.EMAIL_HOST_USER, [to_email], html_message=message)

 

이 때 render_to_string은 아래와 같은 django 내장 함수이다

def render_to_string(template_name, context=None, request=None, using=None):
    """
    Load a template and render it with a context. Return a string.

    template_name may be a string or a list of strings.
    """
    if isinstance(template_name, (list, tuple)):
        template = select_template(template_name, using=using)
    else:
        template = get_template(template_name, using=using)
    return template.render(context, request)

template에 정보를 실어 보내는 것이다 

 

예를 들면

이런 식으로!

그러니까 user, domain, uid, token 값을 email_valid.html에 싣자

django 내장함수인 send_mail을 사용해서 전송하자

 

 

3. uid, token

 

uid와 token을 보자

 

먼저 uid

'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),

 

user.pk 는 자연수이기 때문에 이를 force_bytes를 통해 bytes로 바꿔준다

그리고 urlsafe_base64_encode로 인코딩을 해주자

 

def urlsafe_base64_encode(s):
    """
    Encode a bytestring to a base64 string for use in URLs. Strip any trailing
    equal signs.
    """
    return base64.urlsafe_b64encode(s).rstrip(b"\n=").decode("ascii")

urlsafe_base64_encode를 보면 encode후 decode를 해서 return하기 때문에

따로 decode로 bytes에서 str으로 바꿔줄 필요가 없다.

 

이제 token을 보자

tokens.py파일을 따로 만들어줬다. 관리하기 편하려구?

from django.contrib.auth.tokens import PasswordResetTokenGenerator

from six import text_type


class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        return (text_type(user.pk)) + (text_type(user.email_valid)) + (text_type(timestamp)) 
    

account_activation_token = AccountActivationTokenGenerator()

AccountActivationTokenGeneratorPasswordResetTokenGenerator를 상속받고 있다.

PasswordResetTokenGenerator는 장고에서 제공해주는 class이고 비밀번호를 리셋할 때 token을 발급해주는 기능이 있다. 그래서 user의 pk, 이메일 활성화, 현재시간을 가지고 토큰을 생성해주자

 

 

4.이메일 인증

 

django docs를 보면 

from django.core.mail import send_mail

send_mail(
    'Subject here',
    'Here is the message.',
    'from@example.com',
    ['to@example.com'],
    fail_silently=False,
)
send_mail( 제목 , 메시지 , from_email , recipient_list , fail_silently = False , auth_user = 없음 , auth_password = 없음 , 연결 = 없음 , html_message = 없음 )

이렇다.

 

그렇게 전송을 하고

인증 메일을 확인한 사용자를 활성화하는 API를 만들어주자

 

class UserEmailVaildView(APIView):
    permission_classes = (permissions.AllowAny, )     
    def get(self, request, uidb64, token):
        try:
            uid = force_str(urlsafe_base64_decode(uidb64))
            user = User.objects.get(id=uid)
        except(TypeError, ValueError, OverflowError, User.DoesNotExist):
            user = None

        try:
            if user is not None and account_activation_token.check_token(user, token):
                user.email_valid = True
                user.is_active = True
                user.save()
                user_data = {
                    "username":user.username,
                    "email":user.email,
                    "email_valid":user.email_valid
                }
                return Response(user_data , status=status.HTTP_200_OK)
            else:
                return Response(user_data, status=status.HTTP_400_BAD_REQUEST)
        except:
            return Response(user_data)

 

암호화 했던 uid를 다시 decode 해서 user를 불러온다

그리고 PasswordResetTokenGenerator안에 있는 check_token으로 유효성 검사를 해준다

해당 user가 존재하고 token이 유효하다면 email_valid와 is_active를 활성화 해주자.

 

 

728x90

'STUDY > CS' 카테고리의 다른 글

시스템 호출(시스템 콜, system call, syscall)  (0) 2023.01.13
DFS / BFS  (0) 2023.01.06
TCP / UDP  (0) 2023.01.05
동기 / 비동기  (0) 2023.01.05
프로세스/스레드  (0) 2023.01.05

댓글