2

我正在使用基于 Django 令牌的身份验证。(JWT Token 由 AWS Cognito 等第三方服务生成,我们只验证签名和到期时间)。

这个 REST 应用程序不会有任何用户模型,任何使用 API 调用的人都只需要通过 JWT 令牌进行身份验证。

class JSONWebTokenAuthentication(TokenAuthentication):
    def authenticate_credentials(self, jwtToken):
        try:
            payload = jwt.decode(jwtToken, secret_key,verify=True)
            # user = User.objects.get(username='root')
            user =  AnonymousUser()
        except (jwt.DecodeError, User.DoesNotExist):
            raise exceptions.AuthenticationFailed('Invalid token')
        except jwt.ExpiredSignatureError:
            raise exceptions.AuthenticationFailed('Token has expired')
        return (user, payload)

在视图中:

@api_view(["POST"])
@authentication_classes((JSONWebTokenAuthentication,))
@permission_classes((AllowAny,))

上述过程根本不跟踪 Token。有/无令牌,API 调用正在工作。如果我进行如下两项更改,则它正在工作。

user = User.objects.get(username='root')
#user = AnonymousUser()
@permission_classes((IsAuthenticated,))

一种方法是,在我的应用程序中至少拥有一个用户并引用该用户[此 Web 应用程序可能会在需要时扩展到任意数量的实例,因此必须自动插入具有相同“用户名”的同一用户。]。但是,我可以消除身份验证中的“用户”概念吗?

4

4 回答 4

6

有时你真的不需要用户,例如,服务器到服务器的通信。这是一个解决方案。

覆盖 AnonymousUser 的 is_authenticated 属性,一切顺利

from django.contrib.auth.models import AnonymousUser

class ServerUser(AnonymousUser):

    @property
    def is_authenticated(self):
        # Always return True. This is a way to tell if
        # the user has been authenticated in permissions
        return True

只需在您的自定义身份验证中返回这种新类型的用户

class CustomServerAuthentication(authentication.BaseAuthentication):
    keyword = 'Token'

    def authenticate(self, request):
        auth = get_authorization_header(request).split()

        if not auth or auth[0].lower() != self.keyword.lower().encode():
            return None

        if len(auth) == 1:
            raise exceptions.AuthenticationFailed('Invalid token header. No credentials provided.')

        elif len(auth) > 2:
            raise exceptions.AuthenticationFailed('Invalid token header. Token string should not contain spaces.')

        token = auth[1].decode()

        if not (settings.CUSTOM_SERVER_AUTH_TOKEN == token):
            raise exceptions.AuthenticationFailed('You do not have permission to access this resource')

        user = ServerUser()

        return user, None
于 2020-11-27T12:05:07.803 回答
6

使用django-rest-framework-simplejwt您可以设置DEFAULT_AUTHENTICATION_CLASSES为使用JWTTokenUserAuthentication并且即使没有用户也可以验证令牌。

于 2020-05-19T21:23:09.860 回答
5

Django REST 框架在很大程度上假设请求是基于用户进行身份验证的,但它们确实提供了对身份验证匿名请求的支持。但它通过授予匿名用户某些权限而从“验证(django)用户是真实的”的标准假设中脱颖而出。您的第一个案例的问题是“允许任何”的权限装饰器。

我建议有一个虚拟的 Django 用户。(它也不会阻止您扩展到任意数量的实例)。

利用

user = User.objects.get_or_create(username='whatever')[0]

代替

user =  AnonymousUser()

现在将权限装饰器更改为

@permission_classes((IsAuthenticated,))

除非您设置密码,否则任何人都无法登录此用户,此外,登录此用户不会让您访问您的 API 调用。访问您的 API 的唯一方法是发送一个有效的令牌。

希望这可以帮助。

于 2017-06-01T06:40:22.903 回答
0

您可以使用用户模型而不向数据库插入数据使用:

user = User(id=22,username="someone")

代替:

user = User.objects.get_or_create(username="someone")

或者

 AnonymousUser()
于 2020-12-24T15:31:15.623 回答