프롤로그
일단은...로그인 기능들과 JWT를 한 번에 하려고 했는데 양이 매우 많을 것으로 판단되어 양산형 글 처럼 작성할 거 같다.
JWT사용법과 개념들에 대해서 알아보자.
장고에 JWT 설치하기
pip install djangorestframework djangorestframework-simplejwt
가상환경에서 해당 명령어를 작성한다.
simple jwt 라는 것을 설치하는 것이다
설치가 잘 되었다.
그 후에, 장고 작업하는 곳의 settings.py 에서 설정에 추가하자
INSTALLED_APPS = [
...
"rest_framework",
...
]
INSTALLED_APPS 부분에 하나 추가하고
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}
아무 위치에 이 코드를 추가하자.
그렇다면, 저 REST_FRAMEWORK 부분에 있는 코드는 무엇을 의미하는가?
JSON Web Tokens(JWT)를 사용하여 인증을 수행하는 인증 클래스이다. 이는 djangorestframework-simplejwt 패키지에 정의되어 있으며, 이 설정을 통해 DRF는 들어오는 모든 API 요청에 대해 JWT를 사용하여 인증을 시도하는 것이다. 즉 사용할 인증방식을 전역적으로 설정하는 것이다. 이렇게 되면 DRF가 JWT를 인증 메커니즘으로 사용하도록 지시한다.
JWT 인증 방식의 작동 원리
(1) 토큰 발급
사용자가 로그인 정보(이메일, 비밀번호...)를 포함한 요청을 보내면 서버는 사용자의 정보를 검증한 후 JWT를 발급한다. 이 토큰은 사용자의 식별 정보와 서버가 설정한 만료 시간 등을 포함하고 있으며, 서버의 비밀키로 서명된다.
(2) 토큰 사용
클라이언트는 서버로부터 받은 JWT를 저장해두었다가 이후의 API요청에 포함하여 서버에 전송한다. 일반적으로 HTTP 헤더의 Authorization 필드에 Bearer <토큰> 형식으로 토큰을 추가한다
(3) 요청 인증
DRF는 API 요청을 받을 때마다 "Authorization" 헤더에서 JWT를 추출하고, rest_framework_simplejwt.authentication.JWTAuthentication 클래스를 사용하여 토큰의 유효성을 검증한다. 유효하면 인증, 아니면 오류 반환한다.
이것으로 DRF 기반의 API가 보안을 유지하면서도 쉽게 인증을 처리할 수 있다.
JWT 정리
이정도면 얼추 모르는 개념들은 정리가 된 것 같다. 그러니까 JWT를 다시 쉽게 정리하자면
한 번 로그인 하고 나서 브라우저 껐다가 다시 해당 사이트 로그인 할 때, 다시 로그인 하지 않고, 이 JWT라는 토큰을 발급받아서 이미 로그인이 되어있다라는 것을 보내는 그런 기능이다. HTTP 특성이 한 번 연결이 끊어졌으면 다시 리셋되는 효과가 있는데, 이를 귀찮으니까 계속 로그인 유지하는 기능을 너는 누구고, 몇시부터 몇시까지 써 라고 알려주는 토큰을 줘서 이 토큰으로 계속 로그인되어서 홈페이지를 사용할 수 있게 하는... 쉽게 말하면 이렇다.
이걸 우리가 직접 구현하려면 머리가 아프니, 이미 다른 사람이 API라고 사용설명서를 적어두고 알아서 쓰세요 하고 올려두었고, 우리는 이걸 그냥 사용만 하면 된다 이정도?
로그인 뷰 작성하기
일단...
로그인 뷰부터 작성하자.
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework_simplejwt.tokens import RefreshToken
from django.contrib.auth import authenticate
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
class LoginView(APIView):
def post(self, request):
email = request.data.get('email')
password = request.data.get('password')
user = authenticate(request, email=email, password=password)
if user is not None:
refresh = RefreshToken.for_user(user)
access_token = str(refresh.access_token)
# 사용자 정보를 JSON 형식으로 구성
user_info = {
'email': user.email,
'nickname': user.nickname,
# 추가 필요한 사용자 정보들을 여기에 포함
}
# 응답 구성
response_data = {
'access_token': access_token,
'user_info': user_info,
'message': '환영합니다!'
}
return Response(response_data, status=status.HTTP_200_OK)
else:
return Response({'error': 'Invalid credentials'}, status=status.HTTP_401_UNAUTHORIZED)
email과 password를 post요청으로 보내게 되면,
authenticate(request, email=email, apssword=password)를 통해서 Django의 인증세스템을 사용하여 사용자를 인증하는 역할을 한다.
유효한 경우 해당 사용자를 반환한다.
그리고 user가 유효하다면
리프레시 토큰을 반환하고, 그걸로 액세스 토큰을 반환한다.
그 밑에 user_info와, response_data 는 테스트를 위해서 일단 만들어 놓은 JSON형태의 데이터이다.
테스트를 위해 views.py 아까 위 코드 작성한 밑에 바로
@api_view(['GET'])
@permission_classes([IsAuthenticated]) # 로그인이 필요한 엔드포인트임을 지정
def user_info(request):
user = request.user
# 사용자 정보 구성 (필요한 필드 추가 가능)
user_info = {
'email': user.email,
'nickname': user.nickname,
# 필요한 추가 정보 포함
}
# 응답 데이터 구성
response_data = {
'access_token': '', # 토큰은 이미 로그인 시에 발급되었으므로 빈 문자열
'user_info': user_info,
'message': f"{user.nickname} 환영합니다!"
}
return Response(response_data, status=status.HTTP_200_OK)
이걸 작성한다.
그냥 테스트 용이다.
from django.urls import path
from .views import LoginView,user_info
urlpatterns = [
path('login/', LoginView.as_view(), name='login'),
path('user_info/', user_info, name='user_info'), # 새로 추가
]
urls.py 는 이렇게 수정하고
이제 포스트맨에서 테스트 하자.
포스트맨에서 실험하기
사진처럼 하면 잘 나온다.
이제 토큰으로 로그인해보자. 토큰을 복사해서
이렇게 설정하고 send를 해보자.
테스트 성공이다.
에필로그
내가 뭐라썼는지도 이젠 모르겠다...
일단 됐으니까 해결;
'웹 개발' 카테고리의 다른 글
[장고] 회원가입시 이메일 인증하기(이메일 유효성 검사) #5 (1) | 2024.02.11 |
---|---|
[장고] JWT 사용하기 #4 (0) | 2024.02.10 |
[장고] 회원가입 DRF이용하여 만들기 #2 (0) | 2024.01.30 |
[장고] 프로젝트 Model 작성하기 #1 (1) | 2024.01.29 |
[웹 개발] 개발환경과 서버환경 분리하기 (장고) (0) | 2023.12.24 |