我试图让这个工作,但不知道这是否可行。它应该这样做。
我使用Django
+ Rest-Framework
+ jQuery
开发了一个Web应用程序,我希望有一个外部应用程序来使用相同的REST
API,使用JWT Tokens
进行身份验证。
我当前的配置是这样的。
settings.朋友
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.朋友
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
:
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
在同一个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>
并通过VBA
代码外部:
Set web = CreateObject("WinHttp.WinHttpRequest.5.1")
web.Open "GET", "/api/list/", False
web.SetRequestHeader "Authorization", "Bearer <JWT_TOKEN_HERE>"
web.Send
我无法确切地知道你的情况究竟发生了什么,因为你共享的3个案例中的行为似乎并不一致,但是要简单解释如何在DRF中确定身份验证和授权,这可能有助于你问题出来了。
您应该能够使用两个身份验证类,没有任何问题。使用DRF,身份验证的工作方式如下:
在每次请求时,DRF按照定义的顺序检查提供的身份验证类。每个班级有3个案例:
DRF视图通常使用在设置文件中定义的authentication_classes,但如果您在视图中提供它们,则会覆盖设置。
向视图添加permission_classes时,授权会发挥作用。 permission_classes控制对视图的访问,因此当您将IsAuthenticated添加到视图的权限类时,如果您尝试在没有经过身份验证的用户的情况下访问该视图,则DRF会拒绝该请求并返回403响应。
因此,在您的初始情况下,您的内部ajax请求在这种情况下失败表明您的请求会话中没有经过身份验证的用户数据。我不知道是什么导致这种情况,也许你不在登录视图中更新请求会话(django的登录方法应该自动执行此操作)。
在第二种情况下,您从视图中删除permission_classes,因此无论请求中是否有经过身份验证的用户,视图都将为请求提供服务。因此,期望您的内部ajax请求在此处成功,但我不知道为什么您的外部请求在这种情况下失败。
在第三种情况下,从内部ajax请求的角度来看,场景似乎与第一种情况相同,所以我不知道为什么你的内部ajax请求在这种情况下成功但在第一种情况下不成功。此处的外部请求失败是因为您向视图添加了IsAuthenticated权限类,但未在authentication_classes中包含JWTAuthentication,因此无法使用您的JWT令牌对您的请求进行身份验证。