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()
AccountActivationTokenGenerator는 PasswordResetTokenGenerator를 상속받고 있다.
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,
)
이렇다.
그렇게 전송을 하고
인증 메일을 확인한 사용자를 활성화하는 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를 활성화 해주자.
댓글