Django基于令牌的身份验证,无用户模型

时间:2017-06-01 03:30:33

标签: django django-rest-framework jwt django-authentication pyjwt

我正在使用基于Django Token的身份验证。 (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,))

以上过程中,根本不跟踪令牌。使用/不使用令牌,APi调用正在运行。如果我在下面进行了两次更改,它就会正常工作。

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

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

5 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

Django REST框架主要假设请求是基于用户进行身份验证的,但它们确实为身份验证匿名请求提供支持。但它通过给予匿名用户某些权限来“验证(django)用户是真实的”标准假设脱颖而出。您的第一个案例的问题是具有“允许任何”的权限装饰器。

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

使用

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

而不是

user =  AnonymousUser()

现在将权限装饰器更改为

@permission_classes((IsAuthenticated,))

除非您设置密码,否则此用户无法由任何人登录,而且登录时此用户无法访问您的API调用。访问API的唯一方法是发送有效的令牌。

希望这有帮助。

答案 2 :(得分:1)

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

覆盖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():
            raise exceptions.AuthenticationFailed('Invalid token header')

        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

答案 3 :(得分:0)

尝试验证JWT令牌是否存在。似乎如果它没有,有效载荷只是None而用户是匿名的

答案 4 :(得分:0)

你可以使用 User 模型而无需向数据库插入数据 使用:

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

代替:

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

 AnonymousUser()