SessionAuthentication
:BasicAuthetication
:TokenAuthentication
:rest_framework/authtoken/views.py에 있음.
class ObtainAuthToekn(APIView):
def post(self, request, *args, **kwargs):
....
from rest_framework.authtoken.views import obtain_auth_token
urlpatterns += [
path(r'api-token-auth/', obtain_auth_token),
]
settings.py
INSTALLED_APPS=[
...
'rest_framework', # Third Apps
'rest_framework.authtoken',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
],
}
이후 Migration을 통해 기본 User모델에 Token 필드를 만들어야한다.
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwards):
if created:
Token.objects.create(user=instance)
python3 manage.py drf_create_token <username>
python3 manage.py drf_create_token -r <username>
Token은 rest_framework에서 지원하고, loginRequriedMixin은 Django에서 지원하는 것이라 서로가 호환이 안되어, Token을 제공했음에도 불구하고 로그인화면을 리턴해버림.
역시 스택오버플로우에는 같은 질문이 있었고, 그걸 해결해준 사람이 있었다.
간단하지만 명료하다. Token이 있으면 loginRequiredMixin을 무시하고, 해당 Token에 대한 인증을 ViewSet에서 수행한다. DRF와 Django의 구현이 다르고, Template과 RESTfulAPI 모두를 사용하게되면 계속 겪게될 문제이니 잘 참고하자.
views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from rest_framework.authentication import SessionAuthentication, TokenAuthentication
class TokenLoginRequiredMixin(LoginRequiredMixin):
def dispatch(self, request, *args, **kwargs):
"""If token was provided, ignore authenticated status."""
http_auth = request.META.get("HTTP_AUTHORIZATION")
if http_auth and "Token" in http_auth:
pass
elif not request.user.is_authenticated:
return self.handle_no_permission()
return super(LoginRequiredMixin, self).dispatch(
request, *args, **kwargs)
class MybookWishListViewSet(TokenLoginRequiredMixin, viewsets.ViewSet):
login_url = f'{settings.FORCE_SCRIPT_NAME}/accounts/login'
authentication_classes = [
SessionAuthentication,
TokenAuthentication,
]