Backend/Django

[django-rest-framework] (15) Token 인증

dltjdn 2022. 2. 14. 03:47

DRF에서 지원하는 인증

rest_framework.authentication.SessionAuthentication

  • 웹 프론트엔드와 장고가 같은 호스트를 쓴다면 세션 인증을 사용할 수 있다
  • 하지만 외부 서비스/앱 ( ex. react, 안드로이드 앱)에서는 사용할 수 없다

rest_framework.authentication.BasicAuthentication

  • 매 요청 시마다 인증을 수행한다
  • 매번 username/password를 넘기는 것이 보안상 위험하다

rest_framework.authentication.TokenAuthentication

  • 매 요청 시마다 인증을 수행한다
  • 초기에 username/password로 Token을 발급받고, 이 Token을 매 API 요청에 담아 보내 인증 처리

 

Token 모델

rest_framework에 authtoken 앱 속에 있음

  • User모델과 일대일 관계
  • 각 User별 Token은 수동으로 생성해줘야 한다
  • Token은 유저별로 유일하며, Token 만으로 인증을 수행한다 ← TokenAuthentication 통해

 

Token 생성

 

방법1. authtoken앱의 ObtainAuthToken 뷰를 통한 획득 및 생성

# restframework/authtoken/views.py
class ObtainAuthToken(APIView):
    def post(self, request, *args, **kwargs):
        ...
        token, created = Token.objects.get_or_create(user=user)
        return Response({'token':token.key})

방법2. Signal을 통한 자동 생성

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

방법 3. 커스텀  Management 명령을 통한 생성

# Token이 없을 때 생성하나 생성된 Token을 변경하지 않는다
python manage.py drf_create_token <username>

# 강제로 Token 재생성하기
python manage.py drf_create_token -r <username>

 

Token 획득

1. 먼저 obtain_auth_token을 노출하기

# settings.py
INSTALLED_APPS = [
    ...
    'rest_framework.authtoken'
]

REST_FRAMEWORK = {
	'DEFAULT_AUTHENTICATION_CLASSES" : [
    	'rest_framework.authentication.ToeknAuthentication',
        ...
     ]
  ...
}
    

# urls.py
from rest_framework.authtoken.views import obtain_auth_token

urlpatterns += [
    path('api-token-auth/', obtain_auth_token)
]

 

2. HTTPie를 통한 Token 획득

 

쉘 > http POST http://주소/api-token-auth/ username="유저명" password="암호"

 

→ "token": "9cdd704lfjkd30eignd9oeoghn664048djeiojgio23" 같은 형태로 토큰 할당됨

 

 

3. HTTPie를 통한 Token 활용 예

  • http GET http://localhost:8000/api/post "Authorization: Token 9cdd704lfjkd30eignd9oeoghn664048djeiojgio23" 
  • http POST http://localhost:8000/api/post "Authorization: Token 9cdd704lfjkd30eignd9oeoghn664048djeiojgio23" message="hello"
  • http PATCH http://localhost:8000/api/post/16/ "Authorization: Token 9cdd704lfjkd30eignd9oeoghn664048djeiojgio23" message="patched"