如何在 Django Web 应用程序中处理登录 API

Posted

技术标签:

【中文标题】如何在 Django Web 应用程序中处理登录 API【英文标题】:How to handle login API in Django web app 【发布时间】:2021-12-26 04:38:22 【问题描述】:

我已经使用 Rest Framework 实现了商店 API 列表,包括用户 API、产品 API 等。用户 api 包括基本的登录/注销/注册方法。登录需要用户名和密码,因此 API 调用看起来像 requests.post('api/api_user/login', username='name', password='password')。 Post 方法返回身份验证令牌,如下所示: Post result

问题是我如何使用我的 API 在 Web 应用程序中处理 @login_required。登录的想法很直观,我可以发送 post 请求并获取可以存储在 cookie 中的令牌,但是 Django 使用它自己的身份验证系统来处理用户登录视图(@login_required 装饰器),所以我留下了获取令牌的想法从每个请求中的 cookie 中检查它的正确性,但是这样做是正确的方法吗?我正在寻找应该如何实现这件事的示例或建议。

我的 auth api 实现如下:

from django.contrib.auth import login
from knox.views import LoginView as KnoxLoginView, LogoutView as KnoxLogoutView
from rest_framework import permissions, generics, status
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.response import Response

from .serializers import UserSerializer, RegisterSerializer, ChangePasswordSerializer


class RegisterAPI(generics.CreateAPIView):
    serializer_class = RegisterSerializer
    permission_classes = (permissions.AllowAny,)
    http_method_names = ['post']

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        return Response("user": UserSerializer(user, context=self.get_serializer_context()).data, status=status.HTTP_200_OK)


class LoginAPI(KnoxLoginView):
    serializer_class = AuthTokenSerializer
    permission_classes = (permissions.AllowAny,)
    http_method_names = ['post']

    def post(self, request, format=None):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        login(request, user)
        return super(LoginAPI, self).post(request, format=None)


class ChangePasswordAPI(generics.UpdateAPIView):
    serializer_class = ChangePasswordSerializer
    permission_classes = (permissions.IsAuthenticated,)
    http_method_names = ['put']

    def get_object(self, queryset=None):
        obj = self.request.user
        return obj

    def update(self, request, *args, **kwargs):
        self.object = self.get_object()
        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            if not self.object.check_password(serializer.data.get("old_password")):
                return Response("detail": "Wrong old password", status=status.HTTP_400_BAD_REQUEST)
            self.object.set_password(serializer.data.get("new_password"))
            self.object.save()
            return Response('detail': 'Password updated successfully', status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class LogoutAPI(KnoxLogoutView):
    http_method_names = ['post']

【问题讨论】:

【参考方案1】:

Django 身份验证可用于通过以下方式执行查询,但在您登录并获取会话 ID 和令牌之前。

ses_id = request.session.session_key
token = get_token(request)
cookies = 'csrftoken': token, 'sessionid': ses_id
response = requests.get('http://127.0.0.1:8000/api/api_product/product_types/', cookies=cookies)

【讨论】:

【参考方案2】:

默认情况下,Django 需要会话身份验证。由于您是手动生成令牌,因此您必须在每个 API 中手动对其进行身份验证。为此,您必须编写自定义身份验证方法来解码令牌并检查详细信息。

或者

根据DRF 文档,如果您使用了 DRF 身份验证,则可以使用默认的身份验证权限类。

【讨论】:

我的 api 视图有更新问题,这个想法类似于 DRF 令牌身份验证。我在 Django 中找到了docs.djangoproject.com/en/3.2/topics/auth/customizing 自定义身份验证示例,但我有一些问题,例如如何使用 id 获取用户对象 throw post 方法,而不给其他任何人执行此请求的机会,以实现以下方法,我也有不知道如何从未经身份验证的用户那里保留我的页面 def get_user(self, user_id): try: return User.objects.get(pk=user_id) except User.DoesNotExist: return None 另一个问题是来自 Django Web 和 Rest Framework 会话的 csrf 令牌是否相同?基本上,我可以在 django 视图中获取 csrf 令牌并在调用 API 方法时将其与我的查询一起发布吗? 据我所知,CSRF token 是一样的。 是的,都是一样的,可以一起工作

以上是关于如何在 Django Web 应用程序中处理登录 API的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 django-rest-framework 进行社交登录? [关闭]

Django - 处理用户信息

如何在 Django 和 Python 中使用 JWT(JSON Web 令牌)来创建用于注册和登录的 REST API

如何将Django项目部署到阿里云服务器上

Django - 如何从数据库表中提取登录用户数据?

Django项目部署(nginx+uWSGI+django+virtualenv+supervisor发布web服务器 )