Skip to main content
 首页 » 编程设计

python之Django Rest 框架中的 token 身份验证实现

2025年05月04日34haluo1

我正在使用 Django Rest Framework 开发 API 后端。我最初是使用 session 身份验证开发它的,没有意识到它不能用于发送到移动应用程序。我在 Postman 中尝试用户登录时遇到了 CSRF 保护方面的问题。

现在,由于我必须转向基于 token 的身份验证才能使其正常工作,我该怎么做呢?我想知道如何快速实现它。我浏览了 stackoverflow 上的教程和答案,但无法在实践中实现这一点

还有,Token Authentication是最适合的认证方式吗?我应该使用默认提供的 DRF 模块还是 JWT 或其他一些实现?我可以只对用户登录使用 token 身份验证,对其他 3 个 API 使用 session 身份验证吗?

class UserLogin(APIView): 
queryset = User.objects.all() 
serializer_class = UserSerializer 
def post(self, request, format='json'): 
    username = request.POST.get('username') 
    email = request.POST.get('email') 
    password = request.POST.get('password') 
    user = EmailBackend.authenticate(self,username = email, password = password) 
    if user: 
        id = user.id 
        return Response(id, status=status.HTTP_201_CREATED) 
    else: 
        return Response("Failure", status=HTTP_400_BAD_REQUEST) 
 
class UserRegistration(APIView): 
    queryset = User.objects.all() 
    serializer_class = UserSerializer 
    def post(self, request, format='json'): 
        serializer = UserSerializer(data=request.data) 
        if serializer.is_valid(): 
             user = serializer.save() 
             if user: 
             return Response('Success', status=status.HTTP_201_CREATED) 
        else: 
            return Response(serializer.errors, status=HTTP_400_BAD_REQUEST) 
 
class RecommendationQuestions(generics.ListCreateAPIView): 
    def post(self, request, format = 'json'): 
        """Save the post data when logging in.""" 
        uid = request.data['user_id'] 
        resp_list = MovieSerializer.provide_movie_choices(uid) 
        return Response(resp_list, status=status.HTTP_400_BAD_REQUEST) 
 
class RecommendationGenerator(generics.ListCreateAPIView): 
    queryset = Ratings.objects.all()#.filter(id__in=(1,2)) 
    serializer_class= RatingsSerializer#(queryset,many=True) 
    def post(self, request, format='json'): 
        many = isinstance(request.data, list) 
        serializer = RatingsSerializer(data = request.data, many = many) 
        x = 0 
        if serializer.is_valid(): 
            uid = [d['userId'] for d in serializer.data] 
            resp_list = RatingsSerializer.generate_recommendations(self, uid[0]) 
            return Response(resp_list, status=status.HTTP_201_CREATED) 
        else: 
            return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST) 

这是 API 的 views.py。

请您参考如下方法:

token 认证设置

您通过包含启用 TokenAuthentication

'rest_framework.authtoken' 

在 INSTALLED_APPS 设置中(documentation)。

之后您必须运行 migrate。运行迁移后,您需要为您的用户创建 token 。这是执行此操作的示例代码:

from django.contrib.auth.models import User 
from rest_framework.authtoken.models import Token 
 
users = User.objects.all() 
for user in users: 
    token, created = Token.objects.get_or_create(user=user) 

你只运行一次。此外,您需要为每个新用户创建 token 。您可以使用 post_save 将其自动化信号:

from django.contrib.auth.models import User 
from django.dispatch import receiver 
from django.db.models.signals import post_save 
from rest_framework.authtoken.models import Token 
 
@receiver(post_save, sender=User) 
def create_auth_token(sender, instance=None, created=False, **kwargs): 
    if created: 
        Token.objects.create(user=instance)  

此外,您必须通过包含来添加配置身份验证类

'rest_framework.authentication.TokenAuthentication' 

在您的设置中 'DEFAULT_AUTHENTICATION_CLASSES' ( documentation )

您需要做的最后一件事是将用于 token 身份验证的 url 添加到您的 urls.py:

from rest_framework.authtoken import views as drf_views 
 
urlpatterns += [ 
    path('api-token-auth/', drf_views.obtain_auth_token) 
] 

基于 session 的身份验证用于使用浏览器登录到您的 API。基于 token 的身份验证是无状态的,这意味着服务器不会在服务器上存储有关客户端 session 的任何状态。阅读更多关于差异的信息 here .如果您通过基于 token 的身份验证登录,您将没有 session ,并且无法通过 token 以外的任何其他方式访问 API。

认证示例

下面是使用 requests 在 Python 中进行 token 身份验证的示例代码图书馆。

# Authentication 
import requests 
r = requests.post(<add your token auth url here>, data={'username': 'my_username', 'password': 'my_password'}) 
if r.status_code == 200: 
    response = r.json() 
    token = response['token'] 
    print(token) 

token 必须用于每个其他 API 请求。它通过 header 发送。

# Consume API 
import requests 
headers = {'Authorization': 'Token {}'.format(<your token here>)} 
# Request method is either GET, POST, PUT, PATCH or DELETE 
r = requests.request(method=<request method>, url=<url to api>, headers=headers) 
 
# or you can also use 
# requests.get(url=<url to api>, headers=headers) or 
# requests.post(url=<url to api>, headers=headers, data=<your data>) etc.