[Django Rest Framework] Token
Token
7 min readMar 18, 2020
DRF 인증
- rest_framework.authentication.SessionAuthentication
웹 프론트엔드와 장고가 같은 호스트를 쓴다면, 세션 인증을 사용할 수 있습니다. (nginx 활용)
외부 서비스/앱에서 세션인증 사용X - ~~~.BasicAuthentication
외부 서비스/앱에서 매번 username/password를 넘기는 것은 보안상 위험 - ~~~.TokenAuthentication
초기 username/password로 Token 발급받고 이 Token을 매 API요청에 담아서 보내, 인증을 처리합니다.
Token 모델
User모델과 1:1 관계
각 User별 Token은 수동으로 생성해줘야합니다.
Token은 User별로 유일하며, Token만으로 인증을 수행합니다.
Token 생성 방법
- ObtainAuthToken 뷰를 통한 획득 및 생성 -> URL Pattern 매핑 필요
# rest_framework/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})
키가 없을 시 랜덤하게 키가 지정이 되고 DB에 저장됩니다.
2. Signal 을 통한 자동 생성
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch imort receiver
from rest_framework.authtoken.models import Token@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)
(post_save 이뤄진 후(콜백 처럼))유저 모델 지정해서 그 유저 모델이 저장될 때 호출이 됩니다. created 나 updated 둘다 save가 호출되기 때문에 created=False를 기본값으로 두고 True일 때만 호출이 되어 토큰이 생성이 됩니다.
3. Management 명령을 통한 생성
# 생성된 Token을 변경하지는 않음. 필수X
python3 manage.py drf_create_token <username># 강제로 재생성
python3 manage.py drf_create_token -r <username>
Token 획득
settings.py 에 앱 등록을 합니다.
'rest_framework.authtoken',
.
.
.
obtain_auth_token 노출
from rest_framework.authtoken.views import obtain_auth_tokenurlpatterns += [
path(r’api-token-auth/’, obtain_auth_token),
]
HTTPie 를 이용해서 username과 password를 같이 보냅니다.
http POST localhost:8000/obtain_auth_token/ username=user password=1234
HTTP 요청을 해주면 Token 하나를 생성해줍니다.
이 토큰값은 다시 요청해도 값은 바뀌지 않습니다.
토큰값만 있으면 username과 password 없이도 인증이 가능해집니다.
Token과 HTTPie 활용법
header에다가 Token값을 넣어 보내줘야합니다.
export HOST="http://localhost:800
export TOKEN="***************************************"# Post List
http GET $HOST/api/post/ "Authorization: Token $TOKEN"# Post Create
http POST $HOST/api/post/ "Authorization: Token $TOKEN" message="Hi"# Post Create with Photo
http --form POST $HOST/api/post/ "Authorization: Token $TOKEN" message="Hi" photo@"f1.jpg"# Post #16 Detail
http GET $HOST/api/post/16/ "Authorization: Token $TOKEN"# Post#16 Update
http PATCH $HOST/api/post/16/ "Authorization: Token $TOKEN" message="patched"http PUT $HOST/api/post/16/ "Authorization: Token $TOKEN" message="updated"# Post#16 Delete
http DELETE $HOST/api/post/16/ "Authorization: Token $TOKEN"
# Windows CMD 기준
set TOKEN=***********************http GET localhost:8000/post/1/ "Authorization: Token
%TOKEN%"
아까 obtain_auth_token/ 을 통해서 생성한 토큰값을 가지고 위의 명령어를 통해 조회를 해보면 인증이 됨을 확인할 수 있습니다.
# 파이썬을 통한 처리import requestsHOST = 'http://localhost:8000'
res = requests.post(HOST + '/api-token-auth/', {
'username':'유저명',
'password':'암호',
})res.raise_for_status()token = res.json()['token']
pirnt(token)# 인증이 필요한 요청에 아래의 headers를 붙임
headers = {
'Authorization' : 'Token ' + token, }# Post Detail
res = requests.get("http://localhost:8000/post/1/", headers=headers)
print(res.json())# Post Create
data = {'message' : 'hello requests'}
res = requests.post(HOST + '/api/post/', data=data, headers=headers)
print(res)
print(res.json())# Post Create with Photo
file = {'photo' : open('f1.jpg', 'rb')}
data = {'message' : 'hello requests'}
res = requests.post(HOST + '/api/post/', files=files, data=data, headers=headers)
print(res)
print(res.json())# => 요청에 대한 응답 확인이 가능합니다