首页 > 解决方案 > 缺少 Django CSRF 或需要 Sessions 中间件

问题描述

在尝试创建 django(2) rest framework api 时,我不断收到此错误。

Forbidden (CSRF token missing or incorrect.): /login/

在做了一些研究之后,问题可能出在我并不真正需要的会话身份验证上,因为我将回复基于令牌的身份验证。当我尝试从我的设置中删除一些会话身份验证时,我最终得到了这个。

AssertionError: The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE setting to insert 'django.contrib.sessions.middleware.SessionMiddleware' before 'django.contrib.auth.middleware.AuthenticationMiddleware'.

Settings.py 片段

INSTALLED_APPS = [
    # API (v1)
    'apiV1.v1.accounts.apps.AccountsConfig',

    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Requirements
    'corsheaders',
    'rest_framework',
    'rest_framework.authtoken',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    # 'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'apiV1.urls'

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.TokenAuthentication',
        # 'rest_framework.authentication.SessionAuthentication',
    ),
}

视图.py

from django.contrib.auth import authenticate
from django.shortcuts import get_object_or_404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from apiV1.v1.accounts.models.user import User
from apiV1.v1.accounts.serializers.user import UserSerializerLogin


# login
class LoginView(APIView):
    authentication_classes = ()
    permission_classes = ()

    @staticmethod
    def post(request):
        """
        Get user data and API token
        """

        user = get_object_or_404(User, email=request.data.get('email'))
        user = authenticate(username=user.email, password=request.data.get('password'))
        if user:
            serializer = UserSerializerLogin(user)
            return Response(serializer.data)
        return Response(status=status.HTTP_400_BAD_REQUEST)

标签: djangodjango-rest-frameworkdjango-views

解决方案


如果您不需要会话进行身份验证,则必须使用令牌身份验证。

这是视图的示例

from rest_framework.authtoken.models import Token
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.response import Response

class Login(ObtainAuthToken):
    def post(self, request, *args, **kwargs):
        """
        ---
        serializer: AuthTokenSerializer
        """

        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)

        return Response({
            'pk': user.pk,
            'first_name': user.first_name,
            'last_name': user.last_name,
        })

或者您可以使用JWT身份验证。

这里有一些对您有用的链接。

http://www.django-rest-framework.org/api-guide/authentication/

http://getblimp.github.io/django-rest-framework-jwt/


推荐阅读