简体   繁体   English

Django Rest Framework - 使用会话和令牌身份验证

[英]Django Rest Framework - Using Session and Token Auth

I am trying to get this working but don't know if this is possible.我正在尝试使其正常工作,但不知道这是否可行。 It should be doing it like this.它应该这样做。

I developed a web app using Django + Rest-Framework + jQuery , and I want to have an external application to consume the same REST API, using JWT Tokens for authentication.我使用Django + Rest-Framework + jQuery开发了一个 web 应用程序,我希望有一个外部应用程序来使用相同的REST API,使用JWT Tokens进行身份验证。

My current config is like this.我现在的配置是这样的。

settings.py设置.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',),
    }

views.py视图.py

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)

The tricky part is that when I use:棘手的部分是,当我使用:

permission_classes = (IsAuthenticated,)

I can perform ajax calls from an external application (using a valid JWT token), but jQuery calls from within the app (with an authenticated user) fail with:我可以从外部应用程序(使用有效的JWT令牌)执行ajax调用,但来自应用程序内部的jQuery调用(使用经过身份验证的用户)失败:

{"detail":"Authentication credentials were not provided."}

And on the other hand, if I use autentication_classes instead of permission_classes :另一方面,如果我使用autentication_classes而不是permission_classes

authentication_classes = (SessionAuthentication, BasicAuthentication)

I can perform ajax calls from within the web app using jQuery , but external calls fail with the same 403 error.我可以使用jQuery从 Web 应用程序内部执行 ajax 调用,但外部调用失败并出现相同的403错误。

I tried using both like this:我尝试像这样使用两者:

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

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

but the external calls are also rejected.但外部呼叫也被拒绝。

Is it possible to have these two types of Auth working together in the same class view, or should I separate into two endpoints?是否可以让这两种类型的Auth在同一个class视图中一起工作,还是应该分成两个端点?

EDIT编辑

Example calls from within the app with jQuery :使用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>

And externally via VBA code:并通过VBA代码在外部:

Set web = CreateObject("WinHttp.WinHttpRequest.5.1")
web.Open "GET", "/api/list/", False
web.SetRequestHeader "Authorization", "Bearer <JWT_TOKEN_HERE>"
web.Send

I couldn't work out exactly what is going on in your case, because the behavior in the 3 cases you shared does not seem to be consistent, but going to explain simply how authentication and authorization is determined in DRF, this might help you figure the issue out.我无法弄清楚您的情况到底发生了什么,因为您共享的 3 个案例中的行为似乎不一致,但将简单地解释如何在 DRF 中确定身份验证和授权,这可能会帮助您弄清楚问题出来了。

You should be able to use two authentication classes with no problems.您应该能够毫无问题地使用两个身份验证类。 With DRF, authentication works like this:使用 DRF,身份验证的工作方式如下:

At each request, DRF goes over the provided authentication classes, in the order they are defined.在每个请求中,DRF 按照定义的顺序检查提供的身份验证类。 For each class, there are 3 cases:对于每个类,有 3 种情况:

  1. If it can authenticate the request with the current class, DRF sets request.user .如果它可以使用当前类对请求进行身份验证,则 DRF 设置request.user From this point on, this request is authenticated.从现在开始,这个请求被认证了。
  2. If no authentication credentials are present, DRF skips that class如果不存在身份验证凭据,DRF 将跳过该类
  3. If authentication credentials are present but invalid, such as an invalid JWT token in Authorization header, DRF raises an exception and returns a 403 response.如果身份验证凭据存在但无效,例如Authorization标头中的 JWT 令牌无效,DRF 会引发异常并返回 403 响应。

DRF views normally use the DEFAULT_AUTHENTICATION_CLASSES variable defined in the settings file, but if you provide them in a view, settings are overridden. DRF 视图通常使用设置文件中定义的DEFAULT_AUTHENTICATION_CLASSES变量,但如果您在视图中提供它们,设置将被覆盖。

Authorization comes into play when you add permission_classes to your views.当您将permission_classes添加到您的视图时,授权开始发挥作用。 permission_classes control access to your views, so when you add IsAuthenticated to a view's permission classes, DRF rejects the request with a 403 response if you try to access that view without an authenticated user. permission_classes控制对视图的访问,因此当您将IsAuthenticated添加到视图的权限类时,如果您尝试在没有经过身份验证的用户的情况下访问该视图,DRF 将拒绝该请求并返回 403 响应。

So in your initial case, your internal AJAX request failing in this case suggests that there is no authenticated user data in your request session.因此,在您的初始情况下,您的内部 AJAX 请求在这种情况下失败表明您的请求会话中没有经过身份验证的用户数据。 I do not know what could be causing this.我不知道是什么原因造成的。 Perhaps you do not update request session in your login view (Django's login method should do this automatically).也许您没有在登录视图中更新请求会话(Django 的登录方法应该自动执行此操作)。

In your second case, you remove permission_classes from the view, so the view will serve the request regardless if there is an authenticated user in the request or not.在第二种情况下,您从视图中删除了permission_classes ,因此无论请求中是否存在经过身份验证的用户,视图都会为请求提供服务。 So it is expected that your internal AJAX request succeeds here, but I do not know why your external request fails in this case.所以预计你的内部 AJAX 请求在这里成功,但我不知道为什么你的外部请求在这种情况下失败。

In your third case, from the point of your internal AJAX request, the scenario seems to be the same as the first case, so I do not know why your internal AJAX request succeeds in this case but not in the first case.在您的第三种情况下,从您内部 AJAX 请求的角度来看,情况似乎与第一种情况相同,所以我不知道为什么您的内部 AJAX 请求在这种情况下成功,但在第一种情况下却没有。 The external request failing here is expected because you added the IsAuthenticated permission class to the view, but did not include JWTAuthentication in the authentication_classes, so your request can not be authenticated with your JWT token here.这里的外部请求失败是预料之中的,因为您向视图添加了IsAuthenticated权限类,但没有在 authentication_classes 中包含JWTAuthentication ,因此您的请求无法在此处使用您的 JWT 令牌进行身份验证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM