본문 바로가기
source-code/Django

Django REST Framework _ 인증 기능 구현하기2

by mattew4483 2021. 1. 29.
728x90
반응형

2021/01/25 - [django] - Django REST Framework _ 인증 기능 구현하기

 

Django REST Framework _ 인증 기능 구현하기

모든 웹 API에서 빼놓을 수 없는 인증 기능. 우리의 친절한 DRF에서는 이러한 인증 기능을 쉽게 사용할 수 있는 도구들을 만들어뒀다. www.django-rest-framework.org/tutorial/4-authentication-and-permissions/..

23life.tistory.com

지난번 내용!

User에 대한 정보를 볼 수 있도록 DRF에 추가해줬다.

 

하지만 이렇다고 해서 우리가 원하는 기능이 구현된 건 아니다!

지금은 User와 Post가 각기 따로따로 존재하기 때문.

진정한 인증 기능을 위해 User와 Post를 서로 연결시켜줘야 한다.


 

1. view 수정

views.py

우선 Post 생성 시 작동하는 PostList를 수정해주자!

 

POST 요청 시 실행되는 perform_create란 method를 오버라이딩함으로서 기본 create 함수를 바꿔줄 수 있다.

즉 sesrializer.save(owner=self.request.user)를 통해 PostSerializer 속 field인 owner를 현재의 user로 채운 것!

엥? PostSerializer에 owner가 어디있는디? → 이제 적으러 가보자.

 

2. serializer 수정

Post 작성 시 User와 연결되게끔 → Post를 작성하는 PostSerializer에 담아줄 예정!

 

serializers.py

쨔잔. 이를 통해 PostSerializer에도 owner를 담을 공간을 만들어줬다.

여기서 owner = serializers.ReadOnlyField(source='owner.username')로 지정해줬는데...

ReadOnlyField는 Charfield에 read_only=True를 지정해준 것과 같다.

왜? → owner는 Post 작성시 입력받는 게 아니라 현재 로그인한 user가 들어가야 하니까!

source='owner.username'을 통해 Post 모델 속 owner의 username을 담아주었다.

 

3. permission 생성

우리가 인증 기능을 만들 때...

- 각 Post는 작성한 User와 연결되어 있다.

- 로그인 한 User만 Post 작성이 가능하다. 그렇지 않으면 Post 읽기만 가능!

- 로그인 한 User는 자신이 작성한 Post만 수정 및 삭제가 가능하다.

 

이 세가지를 구현하고 싶었다. 이 중 1번은 완료!

남은 2번, 3번은... permission 즉 허가 를 통해 가능하다.

Post 작성, 수정, 삭제 시 필요한 기능이므로 이를 담당하는 view를 수정해주자.

 

views.py

제일 먼저 rest_framework에서 permissions를 import!

 

views.py

permission_classes를 통해 DRF의 이용자 권한 설정 클래스를 지정해줄 수 있다!

[]로 지정해주는 게 특이하다.

 

여기서는 permissions의 IsAuthenticatedOrReadOnly를 이용.

요놈은 이름 그대로 로그인 되어있으면 해당 view의 모든 기능을(여기서는 R과 C), 그렇지 않으면 R만 승인해준다.

 

views.py

C와 D 역시 로그인 한 유저만 이용할 수 있으므로... IsAuthenticatedOrReadOnly를 추가!

 

4. custom permissions 생성

그런데 이것만으로는? 

로그인 한 사람만 C, U, D를 이용하는 건 좋다만... U와 D는 해당 Post의 owner만 가능해야 한다!

하지만 DRF에 이렇게 친절한 permissions는 존재하지 않는다...!

따라서 직접! 이러한 permissions를 만들어줘야 한다.

우선 앱 내에 permissions.py라는 파일을 생성해준다.

요 녀석의 역할은? 각 Post의 owner만 U, D를 수행할 수 있도록!

 

permissions.py

우선 permissions의 BasePermission을 상속받아 오버라이드!

 

BasePermission을 이용한 custom permission을 위해서는 .has_permission(self, request, view)과

.has_object_permission(self, request, view, obj) 중 하나, 혹은 둘 다를 구현해야 한다.

 

has_permission은 해당 HTTP request에 대한 global 한 승인을,

has_object_permission은 각 object별 승인을 담당!

 

request에 액세스 권한을 부여하고 싶다면 True를, 아니면 False를 반환하면 된다.

 

여기서는 has_object_permission을 통해 특정 객체(object)에 대한 승인을 지정해줄 예정.

 

permissions.py

if request.method in permissions.SAFE_METHODS : ← 이건 또 뭐지?

 

permissions의 SAFR_METHODS란 우리의 데이터베이스에 영향을 줄 일이 없는 HTTP 요청,

즉 GET, OPTIONS, HEAD를 의미한다!

 

permissions.py

따라서 이 녀석은 GET, OPTIONS, HEAD 요청(R) 일 경우 액세스를 승인,

그렇지 않은 요청(U, D) 일 경우 obj.owner(Post 작성자)가 request.user(현재 로그인 한 유저) 일 때 승인!

 

5. view 수정

이렇게 생성한 IsOwnerOrReadOnly란 permission을 해당 view에 적용해주자!

 

views.py

당연히 .permissions에서 만들어준 IsOwnerOrReadOnly를 import 해와야 한다!

 

이를 통해 PostDetail의 U와 D는 Post와 작성자만 접근이 가능해졌다.

 

6. DRF admin 로그인 설정

아니 그런데, 이렇게 열심히 유저 권한을 주면 뭐하나.

유저를 만들어도(createsuperuser로) 로그인, 로그아웃을 할 수가 없는데!

 

역시 우리의 친절한 DRF는 로그인, 로그아웃 기능을 미리 구현해뒀다.

urls.py

쨔잔. Project의 url에 이를 추가해주자!

이것이 도대체 어떤 url 요청인가 하니...

 

 

아하! rest_framework.urls에 login과 logout이 내장되어 있었다!


완성된 결과물을 보니...

http://127.0.0.1:8000/api/posts/

 

각 Post에 owner라는 필드가 생겼고, 작성한 User의 pk가 담겨있다!

 

또한 화면 오른쪽 상단에 Log in 이라는 버튼도 생겼다.

 

또 또한 로그인을 하지 않으니 Post를 작성할 공간도 보이지 않는다!

 

http://127.0.0.1:8000/api/posts/

superuser로 로그인을 하니 POST 요청을 보낼 수 있다!

 

http://127.0.0.1:8000/api/posts/4/

하지만 lee가 작성하지 않은 4번 Post로 가니...

U와 D에 접근할 수가 없다!

 

http://127.0.0.1:8000/api/posts/5/

owner가 lee인 5번 게시글로 가니... U와 D가 가능하다. 와우!

 

인증 기능이 제대로 작동 중!

728x90
반응형