Django REST framework의 Authentication과 Permission에 대해 공부한다.
Posted by
Seoyoung Lee
on August 18, 2020 ·
10 mins read
API요청을 할 때, 아무나 다른 사람의 글을 수정/삭제할 수 있어서는 안되기 때문에 DRF에서는 접근제한을 지원한다. 이를 코드로 살펴보기 위해 Post 모델에 작성자 필드를 추가한다.
Authentication (사용자 인증)
지원하는 인증의 종류 (rest_framework/authentication.py)
1. SessionAuthentication : 세션을 통한 인증 여부 체크
2. BasicAuthentication : Basic 인증헤더를 통한 인증 수행
3. TokenAuthentication : Token 헤더를 통한 인증 수행
4. RemoteUserAuthentication : User 정보가 다른 서비스에서 관리될 때, Remote 인증 / Remote-User 헤더를 통한 인증 수행
포스팅을 저장할 때 현재 인증된 유저 정보를 기록하되, 사용자가 직접 입력하는 방식이 아닌 자동으로 DB에 저장되도록 구현한다. 이를 위해 PostSerializer의 Meta.fields에서 author 필드를 제외시킨다.
그리고 API를 통해 Post 저장 시에 현재 인증된 유저를 지정하도록 perform_create 함수를 오버라이딩한다. serializer.save(**kwargs) 함수는 kwargs 항목을 통해, 추가로 저장할 필드를 지정할 수 있다.
이 상태에서 새로운 포스팅 API를 요청하면 500 에러 응답을 받는다. 요청 시에 인증정보를 제공하지 않았기 때문에 self.request.user에 AnonymousUser 인스턴스가 할당되어 모델 저장에 실패한 것이다.
이를 해결하기 위해 perform_create 함수를 호출하기 전에 인증여부를 체크하는 것이 필요하겠지만 이는 뒤에서 살펴보고 지금은 API 요청 시에 HTTP Basic 인증헤더를 제공하여 성공적으로 API 요청을 처리해본다.
웹브라우저를 통한 로그인/로그아웃 지원
DRF에서는 웹 브라우저에서의 로그인/로그아웃도 지원한다. 아래 코드와 같이 urls.py 를 수정해주면 웹의 오른쪽 상단에 로그인/로그아웃 기능이 추가된다.
Permission (권한 시스템)
Django에서는 기본적으로 is_superuser(별로 permission 없이 모든 권한 허용), is_staff(admin 페이지 접속가능), is_active(False일 경우 로그인 포함 모든 권한 불허)를 제공한다.
또한 DRF에서는 AllowAny(default), IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly 등 여러가지 permission을 제공한다.
권한 지정하기
기본적으로 DRF에서 제공하는 권한을 적용해본다. APIView에서는 permission_classes를 통해 권한을 지정할 수 있다. 우리가 사용하는 ViewSet 역시 APIView를 상속받았으므로 동일하게 권한을 지정한다.
IsAuthenticated 는 인증된 요청에 한해서만 뷰호출을 허용한다. 로그인을 하지 않은 유저는 권한이 없으므로 403 에러가 뜨며, 권한이 없다는 메세지가 출력된다.
커스텀 Permission 만들기
DRF에서 기본 제공해주는 permission만으로 보통 충분하지만, 필요에 의해 커스텀 permission이 필요할 때가 있다. 모든 permission 클래스는 다음 2가지 함수를 선택적으로 구현한다.
- has_permission(request, view) : '뷰 호출 접근권한'으로 APIView 접근 시, 체크
- has_object_permission(request, view, obj) : '개별 record에 대한 접근권한'으로 APIView의 get_object 함수를 통해 object 획득 시, 체크
먼저 기본적으로 구현되어 있는 permission 클래스 코드(rest_framework/permissions.py) 몇가지를 살펴보면,
커스텀 permission을 만들기 위해서는 permission.py 파일을 새로 만들어 위 클래스의 함수를 재정의하면 된다.
포스팅 작성자에 한해서, 수정/삭제 권한을 부여 포스팅 작성자에게만 수정 권한을 부여, 삭제 권한은 superuser에게만 부여
이렇게 permission 함수를 재정의했다면 views.py의 permission_classes에 permission 클래스 이름을 추가해야 적용이 된다.
POST 조회 응답에 작성자 추가
보통 포스팅 조회 응답에는 그 포스팅의 작성자 정보도 같이 제공한다. 이는 PostSerializer를 수정함으로써 구현할 수 있는데, 만약 PostSerializer.Meta.fields에 'author'를 지정한다면 사용자가 항상 입력해야한다는 문제가 있다.
author 필드는 서버에서 인증에 의해서만 지정이 되어야하기 때문에 serializers.ReadOnlyField(source='참조할필드명.속성명')을 쓴다.
위와 같이 serializer를 구현하면 입력을 받을 때에는 'title'필드만 받고 reponse에 대해서는 'author_username'도 표시를 해준다.