JWT 身份验证不适用于 Django 中的自定义控制器

Posted

技术标签:

【中文标题】JWT 身份验证不适用于 Django 中的自定义控制器【英文标题】:JWT authentication doesn't work for custom controller in Django 【发布时间】:2015-08-28 02:12:30 【问题描述】:

我在我的 Python 应用程序中使用 Django Rest Framework,并使用 JSON Web 令牌身份验证 (DRF JWT) 进行 api 身份验证。

我在构建自定义控制器时出现了问题。我将一个特定的 URL 指向了我创建的 calculations.py 文件中的一个函数。以下是它们的外观。

urls.py

from django.conf.urls import patterns, include, url
from django.contrib import admin
from rest_framework import routers 
from app.serializers import xxxViewSet, yyyViewSet
from app.calculations import getReturns

router  = routers.DefaultRouter()
router.register(r"xxx", xxxViewSet)
router.register(r"yyy", yyyViewSet)

urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^api/auth/token/$', 'rest_framework_jwt.views.obtain_jwt_token'),
url(r'^api/auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^api-token-verify/', 'rest_framework_jwt.views.verify_jwt_token'),
url(r'^api/', include(router.urls)),
**url(r'^getReturns/', getReturns),**
)

calculations.py

from django.http import HttpResponse
from .models import xxx, yyy, zzz, aaa

def getReturns(request):
    data = request.GET('data')

    **running calculations here on data and giving out response**

    return HttpResponse(response)

serializers.py

from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework import routers, serializers, viewsets, permissions
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from .models import xxx, yyy, zzz, aaa

class xxxSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = xxx
        fields = ('id', 'name')

class xxxViewSet(viewsets.ModelViewSet):
    authentication_classes = [SessionAuthentication, BasicAuthentication, JSONWebTokenAuthentication]
    permission_classes = [permissions.IsAuthenticated, permissions.IsAdminUser]
    queryset = xxx.objects.all()
    serializer_class = xxxSerializer

上面的serializers.py 文件包含我所有模型的序列化程序类,以及相同的视图集。我还没有将视图集转移到views.py,所以该文件现在是空的。

不管怎样,我的calculations.py与这些文件是分开的,并且这个文件中定义的函数直接被'/getReturns/' URL 调用而不经过视图。如何将计算文件中定义的函数合并到视图集中,以便在函数执行之前调用我的授权类?

【问题讨论】:

【参考方案1】:

我开始在 cmets 中执行此操作,但时间太长了。一般来说,你并没有真正提供足够的代码来提供适当的帮助,但无论如何,这就是我的破解。您正在使用哪个版本/实现的 Django JWT(有一些)、您如何授权您的视图,或者您的计算文件是视图还是其他东西,都不是很明显。 (如果是别的东西,我会在视图中授权,然后从那里调用它。)

为什么您无法发送 POST?通常,一旦您在前端获得令牌,您就可以在任何需要授权的函数上使用 from rest_framework.decorators import authentication_classes@authentication_classes([JSONWebTokenAuthentication,]) 包装器。

看起来像这样:

@authentication_classes([JSONWebTokenAuthentication,])
def function_here(arguments):
    #function does stuff 

您如何传递/尝试将 Web 令牌发送回应用程序?

大概在 CURL 中,您获取令牌的初始身份验证类似于: curl -X POST -d "username=admin&password=abc123 之后你得到(如果你使用rest_framework_jwt)令牌返回: JWTAuthorization: YourTokenHere

之后,将其返回到受 DRF 保护的页面(假设它们已被包装,如上所述,或具有类似的保护) - 您尚未概述您的授权方式 - then from the docs you do: curl -H "Authorization: JWT <your_token>" http://localhost:8000/protected-url/

如果您是在 Angular 或类似软件中生成调用,那么它是相同的 - 您需要在标头中传递它。

编辑:我还注意到,自我最初的回答以来,您已经大大增加了这里的代码量。但从根本上说,您需要检查您声明的身份验证类;最简单的方法是如上所述。

【讨论】:

我现在可以看到我没有提供所有必需的信息。我将它用于 JWT github.com/GetBlimp/django-rest-framework-jwt。 calculations.py 仅包含我在问题getReturns 中提出的一个函数。我没有将它包裹在任何视图中。正如您在url.py 文件中看到的那样,我只是调用此函数并将其附加到URL。我应该把它放到我的views.py 的视图中吗?如果是这样,我该如何执行此操作并使用身份验证进行设置? 我编辑了这个问题。您现在可以看一下并回复吗? 答案还是一样,需要在函数上使用@authentication classes wrapper,在我的答案中。 我已经用一个例子编辑了答案。不过,getblimp 文档相当不错,我会再读一遍,它们包括我在这里所说的一切。 非常感谢。我已经浏览了文档,但在本节中有些困惑。但是,是的,我将再次通过它们。我会尽快将此答案标记为正确。另外,我可以用同样的方式包含@permission_classes吗?

以上是关于JWT 身份验证不适用于 Django 中的自定义控制器的主要内容,如果未能解决你的问题,请参考以下文章

JWT 身份验证适用于 $http.get 但不适用于 $http.post

Django Rest Framework 中 Simple-JWT 的自定义权限

使用 IdentityServer 与创建基于 JWT 的自定义身份验证

JWT:如何在密码或用户名错误 Django REST 上实现我的自定义错误消息

JWT 不适用于快速路由器

Django Rest Framework 不接受 JWT 身份验证令牌