쿠키 세션 방식은 서버측 저장소에 의존하는 한편
토큰 기반 로그인 은 세션 데이터의 서버측 저장소에 의존하지 않는다.
한가지의 계정으로 여러곳에 접속할시(pc,핸드폰 등) 세션을 어떻게 처리할것인가? 에 대한
직면을 해결하기 위한 token 방식 도입
토큰 방식은 일종의 주민등록증 형태이며
발급을 받으면, 사용자의 로컬 환경에 저장하여 인증절차를 거친다.
데이터 용량
cookie 4096 byte
local 5MB
만료
API
임의로 지정하기 위해서는 쿠키는 까다로우나, 로컬은 간편하다.
JSON WEB TOKEN
JWT 확인할 수 있는 사이트
헤더와 페이로드, 서명으로 나뉘어져 있으며
헤더에는 보통 타입과 요청방식
페이로드는 사용자의 추가 데이터 (이름,이메일등등)
서명은 토큰의 무결성을 확인하며, 이에 장고 시크릿키를 통해 무결성을 검증할 수 있다.
pip install djangorestframework-simplejwt
------------------------------------------------------------------
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
------------------------------------------------------------------
settings.py
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework_simplejwt',
'user',
]
------------------------------------------------------------------
app urls.py
from django.urls import path
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
settings.py
AUTH_USER_MODEL = 'user.User'
app.views.py
from rest_framework import status
# 연결상태 전송 헤더
from rest_framework.views import APIView
# API관련 클래스 상속 헤더
from rest_framework.response import Response
from .serializer import UserSerializer
# 사용자 정의 UserSerializer 모델 import
class UserView(APIView):
def post(self,request):
serializer = UserSerializer(data=request.data)
#serializer를 통한 데이터 저장
if serializer.is_valid():
serializer.save()
return Response({"message":"가입완료"},status=status.HTTP_201_CREATED)
return Response({"message":f"${serializer.errors}"},status=status.HTTP_400_BAD_REQUEST)
app.serializer.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
def create(self, validated_data):
user = super().create(validated_data)
# 부모 클래스의 create메서드를 호출
# 인자값을 전달하고 반환값을 user 변수에 담는다.
password = user.password
user.set_password(password)
# 비밀번호 복호화
user.save()
def update(self, instance, validated_data):
...(create메서드와 동일)
async function handleLogin() {
const email = document.getElementById("email").value
const password = document.getElementById("password").value
// HTML 의 각 ID값의 데이터 저장
const response = await fetch("http://127.0.0.1:8000/users/api/token/", {
// fetch post 통신이 완료될때까지 기다리고, api에서는 세션의 토큰을 반환한다.
headers: {
'content-type': 'application/json',
},
method: 'POST',
body: JSON.stringify({
"email": email,
"password": password,
})
})
const response_json = await response.json()
localStorage.setItem("access", response_json.access);
localStorage.setItem("refresh", response_json.refresh);
// 각 토큰을 로컬 스토리지에 저장
async function handleMock() {
const response = await fetch("http://127.0.0.1:8000/users/mock/", {
headers: {
'Authorization': "Bearer " + localStorage.getItem("access")
},
method: 'GET',
})
console.log(response)
}