首页 > 解决方案 > Django-Rest-Framwork 中的会话身份验证,这真的是我必须做的才能使 CSRF 安全吗?

问题描述

首先,这段代码可以工作,只是感觉不像这么简单的东西那么干净。

背景:我正在尝试在 DRF 中创建一个自定义登录 API 端点,该端点将由 React 前端使用。看来您必须手动强制在 DRF 中发送 csrf,这就是我所做的。

我不想通过 Django 表单发送,因为它看起来不像 RESTful,但这是我能找到的唯一避免这种情况的方法。请让我知道这是否是干净的代码。

序列化程序.py

from rest_framework import serializers
from django.contrib.auth import get_user_model # If used custom user model

UserModel = get_user_model()


class UserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True)
    def create(self, validated_data):
        user = UserModel.objects.create_user(
            username=validated_data['username'],
            password=validated_data['password'],
            email=validated_data['email'],
        )

        return user

    class Meta:
        model = UserModel
        # Tuple of serialized model fields (see link [2])
        fields = ( "id", "username", 'email', "password", )


视图.py

from rest_framework import permissions

from django.contrib.auth import get_user_model # If used custom user model
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from .serializers import UserSerializer

from django.utils.decorators import method_decorator
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect


class CreateUserView(APIView):
    model = get_user_model()
    permission_classes = [
        permissions.AllowAny # Or anon users can't register
    ]
    serializer_class = UserSerializer

    @method_decorator(ensure_csrf_cookie)
    def get(self, request, format = None):
        return Response(status=status.HTTP_200_OK)

    @method_decorator(csrf_protect)
    def post(self,request, format = None):
        serializer = UserSerializer(data=request.data)
        if serializer.is_valid():
            serializer.create(serializer.validated_data)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

标签: authenticationsessiondjango-rest-frameworkdjango-rest-auth

解决方案


CSRF 由 Django 启用,而不是 DRF。正如指定的那样,CSRF 保护仅在登录时启动。

登录和注册操作不需要受到 CSRF 保护(因为在 CSRF 攻击场景中需要密码数据,并且无法猜测)。

同样根据 Django 规范,GET 操作/视图不受 CSRF 保护。但是,GET 操作不应更改应用程序的状态。如果不是这种情况,并且您可以在前面实施 CSRF 保护(这对于 REST 应用程序是可能的,但对于默认的 Django 应用程序是不可能的),您可以使用您的装饰器手动保护它。

这主要不是 DRF 问题,而是 Django 问题。


推荐阅读