API của bạn đang mở toang nếu bất kỳ ai cũng gọi được endpoint mà không cần đăng nhập. TokenAuthentication của Django REST Framework giải quyết việc này trong vài dòng cấu hình: server cấp cho mỗi user một token duy nhất, client gửi kèm token trong header Authorization ở mỗi request, và DRF tự xác thực user trước khi view chạy. Cách này phù hợp nhất khi API phục vụ ứng dụng mobile, script bên ngoài hoặc bên thứ ba — những nơi không dùng được session của trình duyệt.
Vấn đề
Giả sử bạn có một ViewSet trả danh sách đơn hàng. Mặc định, DRF không bật xác thực — chỉ cần biết URL là bất kỳ ai cũng đọc được dữ liệu, kể cả dữ liệu nhạy cảm. Dùng SessionAuthentication thì client ngoài trình duyệt phải lo cookie và CSRF token, vừa rườm rà vừa không hợp với mobile app hay script tự động. Bạn cần một cơ chế đơn giản: một “chìa khóa” cố định cho mỗi user, gửi kèm mỗi request, server kiểm tra là xong.
# views.py — API đang mở toang: ai cũng gọi đượcfrom rest_framework import viewsetsfrom .models import Orderfrom .serializers import OrderSerializerclass OrderViewSet(viewsets.ModelViewSet): queryset = Order.objects.all() serializer_class = OrderSerializer
Giải pháp
DRF có sẵn TokenAuthentication, chỉ cần ba bước. Bước một: thêm rest_framework.authtoken vào INSTALLED_APPS rồi chạy migrate — DRF tạo bảng authtoken_token lưu token của từng user. Bước hai: khai báo lớp xác thực mặc định và yêu cầu đăng nhập cho toàn bộ API trong settings. Bước ba: mở endpoint lấy token bằng view có sẵn obtain_auth_token. Từ đây, client chỉ cần đăng nhập một lần để lấy token, rồi gửi kèm token trong header Authorization ở mọi request sau đó. Token lưu trong database nên server khởi động lại cũng không mất, và bạn thu hồi quyền truy cập bất cứ lúc nào chỉ bằng cách xóa token của user đó.
# settings.pyINSTALLED_APPS = [ ... "rest_framework", "rest_framework.authtoken",]REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": [ "rest_framework.authentication.TokenAuthentication", ], "DEFAULT_PERMISSION_CLASSES": [ "rest_framework.permissions.IsAuthenticated", ],}
# urls.pyfrom django.urls import pathfrom rest_framework.authtoken.views import obtain_auth_tokenurlpatterns = [ path("api-token-auth/", obtain_auth_token), # ... các URL khác]
# Lấy token (thay bằng username/password thật)curl -X POST -d "username=linh&password=mat-khau" \ http://127.0.0.1:8000/api-token-auth/# {"token": "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"}# Gọi API kèm tokencurl -H "Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b" \ http://127.0.0.1:8000/api/orders/
Nếu muốn user có token ngay khi đăng ký, gắn một signal post_save vào model User để tự tạo token khi tài khoản mới được tạo — khỏi phải cấp tay từng người.
# accounts/signals.pyfrom django.conf import settingsfrom django.db.models.signals import post_savefrom django.dispatch import receiverfrom 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)
Áp dụng vào dự án của bạn
Áp dụng ngay cho API nội bộ hoặc API phục vụ app mobile: bật TokenAuthentication cho toàn bộ API, chỉ mở ngoại lệ cho endpoint công khai như đăng ký bằng permission AllowAny riêng. Nhớ hai giới hạn: token mặc định không bao giờ hết hạn nên phải đi qua HTTPS để không bị đánh cắp trên đường truyền, và mỗi user chỉ có đúng một token — nếu cần token hết hạn hoặc nhiều token cho nhiều thiết bị, hãy chuyển sang Simple JWT. Thu hồi quyền của một user chỉ cần xóa token của họ trong admin hoặc shell.
Bài viết liên quan
- Django REST Framework: lọc, tìm kiếm và sắp xếp API bằng django-filter trong 5 phút
- Django signals: tự động tạo Profile cho user mới bằng post_save trong 5 phút
- Django REST Framework: thêm endpoint tùy chỉnh bằng @action, khỏi tạo ViewSet mới trong 5 phút
Câu hỏi thường gặp
TokenAuthentication khác gì SessionAuthentication?
SessionAuthentication dùng cookie và CSRF token, hợp với web chạy trên trình duyệt. TokenAuthentication dùng một chuỗi token cố định trong header Authorization, hợp với mobile app, script và bên thứ ba vì không phụ thuộc cookie hay session của trình duyệt.
Token có hết hạn không?
Không. Token của DRF tồn tại vĩnh viễn cho tới khi bạn xóa nó. Muốn token tự hết hạn, dùng djangorestframework-simplejwt hoặc tự thêm trường thời gian hết hạn vào model token của riêng bạn.
Một user có thể có nhiều token không?
Không, mặc định mỗi user chỉ có một token — Token có quan hệ OneToOne với User. Nếu cần nhiều token cho nhiều thiết bị, hãy tự xây model token riêng hoặc dùng Simple JWT với refresh token.
Mất token thì làm sao?
Xóa token cũ trong Django admin hoặc shell rồi tạo token mới cho user đó — token cũ lập tức mất hiệu lực. Client chỉ cần đăng nhập lại để lấy token mới.
💬 Bạn đã thử cách này trong dự án của mình chưa? Nếu gặp lỗi hoặc có cách làm gọn hơn, để lại bình luận bên dưới — mình đọc hết và sẽ bổ sung những ý hay vào bài.
