Django Rest Framework-使用会话和令牌认证

时间:2019-04-06 14:31:07

标签: django python-3.x django-rest-framework django-2.2 django-rest-framework-simplejwt

我正在尝试使其工作,但不知道是否可行。它应该这样做。

我使用Django + Rest-Framework + jQuery开发了一个Web应用程序,我希望有一个外部应用程序可以使用{{1 }}进行身份验证。

我当前的配置是这样的。

settings.py

REST

views.py

JWT Tokens

棘手的部分是当我使用时:

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_classes

我可以使用permission_classes从Web应用程序内执行ajax调用,但是外部调用失败,并出现相同的authentication_classes = (SessionAuthentication, BasicAuthentication) 错误。

我尝试过这样使用两者:

jQuery

但是外部呼叫也被拒绝。

是否可以在同一403视图中同时使用这两种类型的class ListFileView(APIView): authentication_classes = (SessionAuthentication, BasicAuthentication) permission_classes = (IsAuthenticated,) def get(self, request, *args, **kwargs): ... ,还是应该分成两个端点?

编辑

使用Auth从应用程序内部进行调用的示例:

class

并在外部通过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>

1 个答案:

答案 0 :(得分:2)

我无法确切了解您的情况,因为您共享的3种情况下的行为似乎不一致,但仅解释一下如何在DRF中确定身份验证和授权,这可能帮助您解决问题。

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

在每个请求中,DRF都按照定义的顺序遍历提供的身份验证类。对于每个班级,有3种情况:

  1. 如果DRF可以使用当前类对请求进行身份验证,则DRF设置request.user。从这一点开始,此请求已通过身份验证。
  2. 如果不存在身份验证凭据,DRF将跳过该类
  3. 如果存在身份验证凭据但无效,例如授权标头中的JWT令牌无效,则DRF会引发异常并返回403响应。

DRF视图通常使用设置文件中定义的 authentication_classes ,但是如果在视图中提供它们,则设置将被覆盖。

当您在视图中添加 permission_classes 时,

授权就起作用了。 Permission_classes控制对视图的访问,因此,当您在视图的权限类中添加 IsAuthenticated 时,如果您尝试在没有经过身份验证的用户的情况下访问该视图,则DRF会以403响应拒绝请求。

因此,在您的初始情况下,内部ajax请求在这种情况下失败,这表明您的请求会话中没有经过身份验证的用户数据。我不知道是什么原因造成的,也许您未在登录视图中更新请求会话(django的登录方法应自动执行此操作)。

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

在您的第三种情况下,从内部ajax请求的角度来看,方案似乎与第一种情况相同,因此我不知道为什么您的内部ajax请求在这种情况下会成功,但在第一种情况下不会成功。外部请求在此处失败的原因是,您向视图添加了 IsAuthenticated 权限类,但在authentication_classes中不包含 JWTAuthentication ,因此您的请求无法使用JWT令牌进行身份验证在这里。