Session & Cookie
⭐ 쿠키 (Cookie)
- 웹 브라우저와 요청과 응답을 주고받을때 사용하는 데이터 조각
- 쿠키는 도메인에 제한적이며 유효기간이 정해져있음
- Auth 외에도 다양한 방식으로 활용 (광고...?)
⭐ 세션 (Session)
- stateless한 HTTP 특징을 보완하기 위한 방법
- 세션 DB를 이용해서 유저의 정보를 기억하며 Session ID라고 하는 랜덤한 Key를 쿠키에 담아서 Auth에 활용
- 쿠키를 사용해서 Session ID를 주고 받는 것
JSON Web Token, JWT: 쿠키는 웹 브라우저에만 존재. 어플 등 다양한 장치와 소통 필요!
- Token은 간단히 말해 랜덤하게 생긴 문자열이며, 일정한 규칙을 가지고 있고 간단한 서명을 더한 문자열로 토큰 자체에 유저에 대한 간단한 정보가 들어있는 형태
- JWT 방식으로 Auth를 처리하면 Session DB나 인증을 위한 여러가지 로직 처리가 필요 없음.
처리방식
- 클라이언트가 ID/PW를 서버로 보냄
- 서버에서 ID/PW를 검증하고 유효하다면 일정한 형식으로 서명 처리된 Token을 응답
- 이후 클라이언트는 모든 요청 헤더에 토큰을 담아 서버로 요청을 전송
- 서버는 해당 토큰의 유효성을 검증하고 유저의 신원과 권한을 확인 후 요청을 처리
세션과의 차이
- 세션 데이터베이스가 존재하지 않으며 데이터베이스가 필요x
- 토큰 자체가 하나의 인증 데이터
- 서버는 토큰이 유효한지만 검증하여 처리
장점
- 서버에서 관리하는 데이터가 없으므로 복잡한 처리 로직이 필요x
- 세션이나 DB없이 유저를 인증하는것이 가능
단점
- 일방적으로 로그인을 무효화 하는 등의 처리가 불가능 (세션 테이블 없기 때문)
- 모든 기기 로그아웃
- 현재 접속 유저 관리 등
- Token 자체가 데이터를 담고 있는 정보이므로 탈취당할시 보안이 취약
JWT 구조
- https://jwt.io/
- eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
-> . 을 기준으로 HEADER . PAYLOAD . VERIFY SIGNATURE 세 부분으로 구성
- HEADER
- 토큰의 타입(jwt) 또는 서명 부분의 생성에 어떤 알고리즘(alg)이 사용되었는지 등을 저장
- PAYLOAD
- 토근 발급자, 토큰 대상자, 토큰 만료시간, 활성날짜, 발급시간 등등
- 여러 데이터가 담겨있는 부분
- 이곳에 서비스가 유저 정보를 담아서 인증
- 누구나 풀어볼 수 있기 때문에 민감한 정보를 담지않고 최소의 정보만 저장
- user의 pk 값 등
- 각각의 데이터는 Claim이라고도 하며 Key-Value 형태로 구성됨
- SIGNATURE
- HEADER + PAYLOAD + 서버의 비밀키 값을 HEADER에 명시된 암호 알고리즘 방식으로 생성한 값
- 즉 PAYLOAD의 글자 하나만 달라져도 SIGNATURE는 완전히 다른 문자열로 변환되어 서버의 비밀키 값을 모른다면 유효한 서명값을 만들어내는 것이 불가능
- 서버는 토큰을 받으면 HEADER + PAYLOAD + 비밀키로 생성한 서명값이 토큰의 서명값과 일치하는지를 확인하는 과정을 거쳐서 유효성 여부를 확인
- 서명의 유효여부 + 유효기간 내의 토큰인지 확인하여 Auth 과정을 처리
Access Token과 Refresh Token
- 토큰이 털리면 큰일남.
→ 유효기간을 짧게 둬버림
➡️ Access Token
- 요청할 때 인증을 위해 헤더에 포함해야하는 토큰
- 매 요청시 보내는 토큰이므로 보안이 취약
- 만료 기한을 짧게 잡아 만약 탈취 당해도 짧은 시간안에 유효하지 않은 토큰 형태
🔃 Refresh Token
- Access Token이 만료되었을때 새로 Access Token을 발급받기 위한 Token
- Access Token 보다 긴 유효기간
- 주로 사용자의 기기에 저장해두고 사용되며 만약 Refresh Token까지 만료되었다면 다시 인증(로그인) 과정이 필요
- Refresh Token의 탈취를 보완하기 위해 DB 리소스를 사용하는 다양한 방식도 존재합니다. (BlackList 등)
JWT 구현하기
https://django-rest-framework-simplejwt.readthedocs.io/en/latest/index.html
pip install djangorestframework-simplejwt
settings.py
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework_simplejwt.authentication.JWTAuthentication",
],
}
accounts/urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path("signin/", TokenObtainPairView.as_view(), name="token_obtain_pair"),
path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
]
Login JSON(superuser)
{
"username": "admin",
"password" : "admin1234"
}
JWT 유효기간 설정(JWT customizing)
from datetime import timedelta
...
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=1),
"REFRESH_TOKEN_LIFETIME": timedelta(days=1),
"ROTATE_REFRESH_TOKENS": True,
"BLACKLIST_AFTER_ROTATION": True,
}
from datetime import timedelta
...
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=1), # access token 유효시간 1분
"REFRESH_TOKEN_LIFETIME": timedelta(days=1), # refresh token 유효시간 하루
"ROTATE_REFRESH_TOKENS": True, # refresh요청 할때마다 다시 refresh token 줌
"BLACKLIST_AFTER_ROTATION": True, # 이전 refresh token 블랙리스트 테이블에 올림
}
03. 접근 제한하기: 로그인 후 이용가능을 JWT로 구현
유저가 아니면 Article 기능 접근 제한
articles/views.py
from rest_framework.permissions import IsAuthenticated # 이부분과
...
class ArticleListAPIView(APIView):
permission_classes = [IsAuthenticated] # 이부분만 추가함
def get(self, request):
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
def post(self, request):
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
Token을 이용해서 인증하기
- Token 정보는 요청 Header에 담아서 전달
- postman은 보다 편리하게 auth를 담을 수 있도록 편의 기능을 제공
Access Token의 유효기간을 1분으로 잡아놓아서 그럼. 이렇게 짧게 설정하는 것이 안전하지만 지금 테스트를 하며 개발하고 있기 때문에 기간을 조금 늘려도 괜찮음.
- Bearer
- JWT 혹은 OAuth에 대한 토큰임을 명시하는 것 (RFC 6750)
- 이 값도 특정 단어로 변경할 수 있으나 권장하지 않음.(그냥 쓰세요)
'Django' 카테고리의 다른 글
Django ORM 최적화 (0) | 2024.08.30 |
---|---|
Django ORM (심화) (0) | 2024.08.30 |
Serializer 활용하기 (0) | 2024.08.29 |
Relationship과 DRF(with. particular seed) (0) | 2024.08.29 |
DRF CBV (0) | 2024.08.29 |