JWT, Session, API Key 인증을 한 번에 지원하기
현대적인 서비스는 웹 브라우저, 모바일 앱, 외부 서비스 등 다양한 클라이언트를 지원해야 하므로, 각 환경에 최적화된 여러 인증 방식을 동시에 제공하는 것이 필수

여러 인증 방식이 필요한 이유
웹 브라우저 (SPA): Session 인증이나 JWT 방식 사용 모바일 앱: 서버 부담이 적고 확장성이 좋은 JWT 방식 선호 외부 서비스: 서버 간 통신을 위한 고정된 API Key 인증 사용
DRF 인증 처리 방식
DRF는 authentication_classes에 설정된 인증 클래스들을 순서대로 실행하여 사용자 식별
첫 번째 클래스부터 순차적으로 인증 시도
하나의 인증 클래스가 성공하면 뒤 순서 클래스들은 실행되지 않음
인증 성공 시
request.user와request.auth속성 설정모두 실패하면
request.user는AnonymousUser로 설정
구현 방법
API Key 인증 클래스 구현
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import APIKey
class APIKeyAuthentication(BaseAuthentication):
def authenticate(self, request):
api_key_str = request.headers.get('X-API-KEY')
if not api_key_str:
return None
try:
api_key = APIKey.objects.get(key=api_key_str, is_active=True)
user = api_key.user
except APIKey.DoesNotExist:
raise AuthenticationFailed('Invalid API Key.')
return (user, api_key)View에 인증 클래스 설정
from rest_framework.views import APIView
from rest_framework.authentication import SessionAuthentication
from rest_framework_simplejwt.authentication import JWTAuthentication
from .authentication import APIKeyAuthentication
class CombinedAuthView(APIView):
authentication_classes = [SessionAuthentication, JWTAuthentication, APIKeyAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request):
return Response({
'message': f'Hello, {request.user.username}!',
'auth_method': request.auth.__class__.__name__
})인증 순서의 중요성
[Session, JWT, APIKey]
웹 브라우저 호환성 최우선, CSRF 보호 정상 동작
JWT 토큰이 있어도 Session이 우선 처리됨
[JWT, Session, APIKey]
Stateless API 우선, 성능 유리
CSRF 보안 취약점 발생 가능
실무 권장사항
엔드포인트 목적별 분리
웹 프론트엔드용:
[SessionAuthentication, JWTAuthentication]모바일/외부 서비스용:
[JWTAuthentication, APIKeyAuthentication]
성능 최적화
불필요한 인증 클래스 제거
API Key 인증에 캐싱 적용 고려
동적 인증 클래스 변경
def get_authenticators(self):
if self.request.method == 'GET':
return [APIKeyAuthentication()]
return [JWTAuthentication(), SessionAuthentication()]Last updated
