Python Django Rest框架-使用会话和令牌身份验证

Python Django Rest框架-使用会话和令牌身份验证,python,django,django-rest-framework,django-rest-framework-simplejwt,Python,Django,Django Rest Framework,Django Rest Framework Simplejwt,我正试图让这项工作,但不知道这是否是可能的。它应该这样做 我使用Django+Rest框架+jQuery开发了一个web应用程序,我希望有一个外部应用程序使用相同的RestAPI,使用JWT令牌进行身份验证 我当前的配置是这样的 设置.py REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication',

我正试图让这项工作,但不知道这是否是可能的。它应该这样做

我使用
Django
+
Rest框架
+
jQuery
开发了一个web应用程序,我希望有一个外部应用程序使用相同的
Rest
API,使用
JWT令牌
进行身份验证

我当前的配置是这样的

设置.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_RENDERER_CLASS': [
        'rest_framework.renderers.JSONRenderer',
    ]
}

SIMPLE_JWT = {
    'AUTH_HEADER_TYPES': ('Bearer',),
    }
class ListFileView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, *args, **kwargs):
        user = request.user

        if user:

            obj = Foo.objects.filter(owner=user)
            serializer = FooSerializer(obj, many=True)
            data = serializer.data

            return Response(data, status=status.HTTP_200_OK)

        return Response({'detail': 'You have no access to files.'}, status=status.HTTP_400_BAD_REQUEST)
视图.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_RENDERER_CLASS': [
        'rest_framework.renderers.JSONRenderer',
    ]
}

SIMPLE_JWT = {
    'AUTH_HEADER_TYPES': ('Bearer',),
    }
class ListFileView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, *args, **kwargs):
        user = request.user

        if user:

            obj = Foo.objects.filter(owner=user)
            serializer = FooSerializer(obj, many=True)
            data = serializer.data

            return Response(data, status=status.HTTP_200_OK)

        return Response({'detail': 'You have no access to files.'}, status=status.HTTP_400_BAD_REQUEST)
棘手的是,当我使用:

permission_classes = (IsAuthenticated,)
我可以执行来自外部应用程序的
ajax
调用(使用有效的
JWT
令牌),但是来自应用程序内部的
jQuery
调用(使用经过身份验证的用户)失败:

{"detail":"Authentication credentials were not provided."}
另一方面,如果我使用
autentication\u classes
而不是
permission\u classes

authentication_classes = (SessionAuthentication, BasicAuthentication)
我可以使用
jQuery
在web应用程序中执行ajax调用,但是外部调用失败,并出现相同的
403
错误

我试着用这两种方法:

class ListFileView(APIView):
    authentication_classes = (SessionAuthentication, BasicAuthentication)
    permission_classes = (IsAuthenticated,)

    def get(self, request, *args, **kwargs):
        ...
但外部电话也被拒绝

是否可以让这两种类型的
Auth
在同一
视图中一起工作,或者我应该分成两个端点

编辑

使用
jQuery
从应用程序内部调用的示例:

<script type="text/javascript">

function loadTblDocs() {
  $("#tbl-docs > tbody").empty();

  $.ajaxSetup({
      headers: { "X-CSRFToken": '{{csrf_token}}' }
    });

  $.ajax({
    type: 'GET',
    contentType: "application/json; charset=utf-8",
    url: "/api/list/",
    dataType: "json",
    success: function (data) {
                console.log(data);
                }
    });
};

</script>

我无法确定您的案例中到底发生了什么,因为您共享的3个案例中的行为似乎不一致,但简单地解释一下如何在DRF中确定身份验证和授权,这可能会帮助您解决问题

您应该能够毫无问题地使用两个身份验证类。使用DRF,身份验证的工作方式如下:

class ListFileView(APIView):
    authentication_classes = (SessionAuthentication, BasicAuthentication)
    permission_classes = (IsAuthenticated,)

    def get(self, request, *args, **kwargs):
        ...
在每个请求中,DRF按照定义的顺序检查提供的身份验证类。对于每个类别,有3种情况:

  • 如果可以使用当前类验证请求,DRF将设置
    request.user
    。从这一点开始,这个请求就被验证了
  • 如果不存在身份验证凭据,DRF将跳过该类
  • 如果身份验证凭据存在但无效,例如
    授权
    头中的JWT令牌无效,DRF将引发异常并返回403响应
  • DRF视图通常使用设置文件中定义的
    DEFAULT\u AUTHENTICATION\u CLASSES
    变量,但如果在视图中提供这些变量,则会覆盖设置

    权限\u类添加到视图中时,授权开始发挥作用
    permission\u classes
    控制对视图的访问,因此当您将
    IsAuthenticated
    添加到视图的权限类中时,如果您试图在没有经过身份验证的用户的情况下访问该视图,DRF将以403响应拒绝该请求

    因此,在最初的情况下,您的内部AJAX请求在本例中失败表明您的请求会话中没有经过身份验证的用户数据。我不知道这是什么原因造成的。也许您没有在登录视图中更新请求会话(Django的登录方法应该自动完成这项工作)

    在第二种情况下,从视图中删除
    权限类
    ,因此无论请求中是否有经过身份验证的用户,视图都将为请求提供服务。因此,我们期望您的内部AJAX请求在这里成功,但我不知道为什么您的外部请求在这种情况下失败


    在第三种情况下,从内部AJAX请求的角度来看,场景似乎与第一种情况相同,因此我不知道为什么内部AJAX请求在这种情况下成功,但在第一种情况下没有成功。预期外部请求在此失败,因为您将
    IsAuthenticated
    权限类添加到视图中,但未将
    JWTAuthentication
    包含在身份验证类中,因此,您的请求无法在此处使用JWT令牌进行身份验证。

    您可以显示如何调用API吗?@JPG使用
    jQuery
    或外部调用?@JPG添加了
    jQuery
    VBA
    示例调用。您也可以发布登录视图吗?您是否使用Django的登录方法?是的,我使用的是标准Django登录您是对的,谢谢您的详细解释。事实证明,我实际上在生产中使用了一个错误的
    settings.py
    文件,该文件缺少DRF
    DEFAULT\u authentication\u CLASSES
    中的这一行
    rest\u framework.authentication.SessionAuthentication
    ,现在工作正常。