如何在 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 和 Python 中使用 JWT(JSON Web 令牌)来创建用于注册和登录的 REST API
Django项目部署(nginx+uWSGI+django+virtualenv+supervisor发布web服务器 )