Django

Django Rest Framework 인증 관련 설정

behonestar 2017. 1. 23. 20:31

Django 프로젝트의 settings.py에는 인증 관련 설정이 몇가지 있는데 각각 어떤 역할을 하는지 정리해보았습니다.

AUTHENTICATION_BACKENDS

로그인 시 username, password을 인증할 Backend를 정의합니다.

Django의 authenticate 함수에 의해 호출됩니다.

명시적으로 정의하지 않으면 기본값으로 아래의 설정이 적용됩니다.

AUTHENTICATION_BACKENDS = (

'django.contrib.auth.backends.ModelBackend',

)


Django로 로그인 기능을 만든다면 아래처럼 구현할 것입니다.

authenticate 함수가 실행되면 ModelBackend를 사용하여 인증을 합니다.

from django.contrib.auth import authenticate, login


def login_view(request):

    username = request.POST['username']

    password = request.POST['password']

    user = authenticate(username=username, password=password)


    if user is not None:  

        # 인증 성공 -> 로그인(session framework에 user 등록됨)

        login(request, user)

        ...

    else:

        # 인증 실패

        ...



DEFAULT_AUTHENTICATION_CLASSES

API가 호출됐을 때 session이나 token을 인증할 클래스들을 정의합니다.

Django Rest Framework의 APIView에 의해 호출됩니다.

명시적으로 정의하지 않으면 기본값으로 아래의 설정이 적용됩니다.

REST_FRAMEWORK = {

    'DEFAULT_AUTHENTICATION_CLASSES': (

        'rest_framework.authentication.SessionAuthentication',

        'rest_framework.authentication.BasicAuthentication'

    ),

}


아래 예제에서 list()에 해당하는 API를 호출하면, 가장 먼저 위의 인증 클래스들부터 실행됩니다.

from rest_framework import viewsets

from rest_framework.response import Response



class ExampleViewSet(viewsets.ViewSet):

    def list(self, request):

        return Response('authentication passed')


View에서 호출될 인증 클래스들을 특정하고 싶다면 authentication_classes 변수를 정의하면 됩니다.

from rest_framework import viewsets

from rest_framework.response import Response

from rest_framework.authentication import SessionAuthentication


class ExampleViewSet(viewsets.ViewSet):

    authentication_classes = (SessionAuthentication, )


    def list(self, request):

        return Response('authentication passed')


rest_auth 모듈의 인증 흐름

rest_auth 모듈의 로그인 소스코드입니다. (rest_auth.views.LoginView)

① GenericAPIView도 APIView를 상속하므로 DEFAULT_AUTHENTICATION_CLASSES에 정의된 인증을 거칩니다.

② serializer valid 체크 시 authenticate 함수가 호출되므로 AUTHENTICATION_BACKENDS에 정의된 인증을 거칩니다.

class LoginView(GenericAPIView):

    ...

    def login(self):

        #2. rest token 생성

        self.user = self.serializer.validated_data['user']

        self.token = create_token(self.token_model, self.user, self.serializer)


        #3. django.contrib.auth.login 호출 -> session에 user 등록됨

        if getattr(settings, 'REST_SESSION_LOGIN', True):

            login(self.request, self.user)

    ...

    def post(self, request, *args, **kwargs):

        self.serializer = self.get_serializer(data=self.request.data)


        #1. 인증

        self.serializer.is_valid(raise_exception=True)

            validate()

                _validate_username(username, password)

                    authenticate(username=username, password=password)


        self.login()


        #4. token 리턴

        return self.get_response()