在Django中使用外部API进行基于令牌的身份验证(DRF)

x0fgdtte  于 2022-11-18  发布在  Go
关注(0)|答案(1)|浏览(193)

上下文

我的API接受一个jwt-token,我可以将它传递给一个外部端点,如果无效/过期,它将返回401,如果仍然有效,它将返回用户信息。基于此,我将返回401或属于该用户的过滤数据。同样,POST请求需要涉及写入该资源属于谁,以便GET工作。我尝试通过覆盖get_queryset和perform_create方法来做到这一点。
我的视图集如下所示:

class ReportViewSet(AuthorizedUserBasedFilteredViewset):
    queryset = Report.objects.all()
    serializer_class = ReportSerializer

    def perform_create(self, serializer):
        try:
            username = self.get_authorized_user()['user']['username']
        except Exception as e:
            return Response({'error': 'Token does not exist'}, status=HTTP_401_UNAUTHORIZED)
        serializer.save(creatd_by=username)

    def get_queryset(self):
        try:
            username = self.get_authorized_user()['user']['username']
        except Exception as e:
            return Response({'error': 'Token does not exist'}, status=HTTP_401_UNAUTHORIZED)
        return Report.objects.filter(created_by=username)

这不起作用,因为get_queryset需要一个queryset作为响应。

个问题

1.如何在get_queryset中引发authorize异常?是否有其他方法应该完全覆盖身份验证?我仍然需要将username received传递给get_queryset以使身份验证成功
1.是否有更好的方法来实现这一点?我认为调用外部身份验证API并将用户设置为可通过get_queryset和perform_create方法访问,理想情况下应该在代码中的其他地方进行。我查看了RemoteUserAuthenticationBackend,但它仍然涉及创建User对象,但对于本用例,用户模型完全是外部的

nzk0hqpo

nzk0hqpo1#

代替

return Response({'error': 'Token does not exist'}, status=HTTP_401_UNAUTHORIZED)

用这个

raise NotAuthenticated(detail='Token does not exist')

希望上面的行已经回答了您的第一个问题。
对于第二个问题,您可以扩展TokenAuthentication,然后实现def authenticate_credentials(self, key):方法。每次调用外部API获取用户不是一个好主意。相反,您应该从外部源获取一次JTW标记,然后在每个API调用的标头中传递JWT标记(如Authorization : Bearer cn389ncoiwuencr)。然后,您应该在当前系统中解码JWT标记。

from rest_framework.authentication import TokenAuthentication
from django.contrib.auth import get_user_model
class CustomTokenAuthentication(TokenAuthentication):
    keyword = 'Bearer' # token type
    def authenticate_credentials(self, key):
        #decode JWT.
        username = get_username()
        User = get_user_model()
        user = User(username=username)
        return user, key

最后,将该类添加到settings.py文件中。

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'path.of.CustomTokenAuthentication',
    )
}

这将应用于您的所有视图。或者您可以使用视图特定的auth类。

class Sample(ViewSet):
    authentication_classes = (CustomTokenAuthentication,)

从现在开始,你可以通过request.user在视图或视图集访问用户。就是这样。

相关问题