Server/django

[Django] Authentication & Permission

또잉코딩 2020. 5. 29. 14:11

운영 원리 : Authentication & Permission

제 3자를 비롯한 모든 사용자에게 동일한 권한을 주는 경우는 극히 드물다.

 

Authentication

서비스를 이용하는 데에 있어 내가 어느 정도의 권한이 있음을 알려주는(요청하는) 과정

 

Authentication - Django REST framework

 

www.django-rest-framework.org

 

BasicAuthentication

HTTP 자체 기본인증에 기반한 인증방식

HTTP 제어 헤더로 넘긴 ID, PW를 base64 encoding

 

TokenAuthentication

BasicAuthentication은 보안에 취약하다는 단점

SessionAuthentication은 외부 서비스에서 사용할 수 없다는 단점을 가진 한계로

많은 서비스에서 사용된다.

Mobile Client에 적합

수행과정

1. username과 password를 받아 1:1로 매칭되는 고유 Key 생성 및 발급 (User instance의 생성에 따라 자동으로 생성되는 것은 아님)

2. 발급받은 Token을 API 요청에 담아 인증처리

 

1. settings.py

INSTALLED_APPS = [
    'rest_framework.authtoken',
]

2. views.py

from .models import UserPost
from .serializer import UserPostSerializer
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication

class UserPostViewSet(viewsets.ModelViewSet):
    authentication_classes = [TokenAuthentication]
    queryset = UserPost.objects.all()
    serializer_class = UserPostSerializer

3. $ python manage.py migrate

authtoken/models.py의 OneToOneField를 이용해 Token을 발급할 것이기 때문이다.

4. 

(1) rest_fraemwork/authtoken/views.py의 ObtainAuthToken을 이용한 생성

(2) Python 명령어를 통한 생성

$ python manage.py drf_create_token <username>

$ python manage.py drf_create_token -r <username> : token을 강제로 재발급

+ 자동으로 token이 생성되기를 원한다면 signal을 이용한 Token 획득

*post_save : DB에 뭔가가 저장된 직후에 특정 동작 수행

5. 생성한 Token을 획득하기 위해 token을 획득할 수 있는 url path 지정한다.

6. url에 대해 POST 요청을 보냄으로써 획득

POST 요청 보낼 때 "Authorization: Token <token>"를 함께 보낸다.

http POST http://127.0.0.8000/userpost/ "Authorization: Token <token>" title="" body=""

7. 

인증 성공시 : 

request.user = Django User Instance

request.auth = rest_framework.authtoken.models.BasicToken

 

SessionAuthentication

로그인 될 때마다 저장되는 Session 정보를 참조하여 인증

 

RemoteUserAuthentication

User 정보가 다른 서비스에서 관리될 때 쓰이는 인증방식 == 원격지에서의 인증방식

 

 

전역으로 설정하는 방법

settings.py

DEBUG = False

ALLOWED_HOSTS = ['*']



REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}

 

지역으로 설정하는 방법

views.py

from .models import UserPost
from .serializer import UserPostSerializer
from rest_framework import viewsets
from rest_framework.authentication import SessionAuthentication, BasicAuthentication

class UserPostViewSet(viewsets.ModelViewSet):
    authentication_classes = [SessionAuthentication, BasicAuthentication]
    queryset = UserPost.objects.all()
    serializer_class = UserPostSerializer

 

serializer.py

from .models import UserPost
from rest_framework import serializers

class UserPostSerializer(serializers.ModelSerializer):
    
    author_name = serializers.ReadOnlyField(source='author.username')

    class Meta:
        model = UserPost
        fields = ['pk', 'author_name', 'title', 'body']

 

HTTPie에서 인증 요청 보내는 방법

http --auth username:password --form POST http://127.0.0.1:8000/userpost/ title="" body=""

→ 예를 들어, http --auth sss20-02:1234 --form POST http://127.0.0.1:8000/userpost/ title="" body=""

 

 

Permission

(인증 요청을 보낸 사용자에 대해서) 서비스를 어느 정도로 이용할 수 있는지에 대한 권한

View 호출 시 가장 먼저 체킹

인증 정보를 기반으로 권한 체크(request.user, request.auth 를 기반으로 권한 체크)

 

Permissions - Django REST framework

 

www.django-rest-framework.org

 

AllowAny

디폴트로 설정된 클래스로, 인증된 요청이든 비인증 요청이든 전부 허용하겠다.

 

IsAuthenticated

인증된 요청에 대해서만 View호출을 허용하겠다(등록된 사용자에게만 Access 허용)

 

IsAdminUser

StaffUser에 대해서만 요청을 허용하겠다

(User.is_staff == True 일 대만 허용)

 

IsAuthenticatedOrReadOnly

비인증 요청에 대해서는 읽기만 허용하겠다

(비인증 요청은 '안전한 http method'만 허용하겠다)

 

전역으로 설정하는 방법

settings.py

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ]
}

 

지역으로 설정하는 방법

views.py

from .models import UserPost
from .serializer import UserPostSerializer
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated

class UserPostViewSet(viewsets.ModelViewSet):
    permission_classes = [IsAuthenticated]
    queryset = UserPost.objects.all()
    serializer_class = UserPostSerializer

+ FBV decorator를 이용한 설정

from rest_framework.permissions import IsAuthenticated

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def example_view(request, format=None):

 

 

Tip. 로그인/로그아웃 버튼 생성

urls.py 에 추가

from django.urls import path, include
from rest_framework import urls

urlpatterns = [
    path('api-auth/', include('rest_framework.urls')),
]

이때, authentication_classes = [TokenAuthentication] 이 있어야 한다.

'Server > django' 카테고리의 다른 글

[Django] Filtering & Search  (0) 2020.05.25
[Django] Pagination  (0) 2020.05.25
[Django] View of DRF ( Django Rest Framework )  (0) 2020.05.04
[Django] JSON 직렬화 - Serializer  (0) 2020.04.28
[Django] REST Architecture  (0) 2020.04.28