解决 DjangoRestFramework 的 TokenAuthentication Token 没有过期的问题

上篇我们介绍了 DjangoRestFramework 的 TokenAuthentication 方案,同时提到了该方案有个问题是 Token 永远不过期。本文我们就利用继承 DjanoRestFramework 的 TokenAuthentication 重写其中的 authenticate_credentials 方法来实现给 Token 加个有效期。

# 自定义的ExpiringTokenAuthentication认证方式
class ExpiringTokenAuthentication(TokenAuthentication):
    model = Token

    def authenticate(self, request):
        print("authenticate")
        auth = get_authorization_header(request)

        if not auth:
            return None
        try:
            token = auth.decode()
        except UnicodeError:
            msg = _('Invalid token header. Token string should not contain invalid characters.')
            raise exceptions.AuthenticationFailed(msg)
        print("token",token)
        return self.authenticate_credentials(token)

    def authenticate_credentials(self, key):
        model = self.get_model()
        try:
            token = model.objects.select_related('user').get(key=key)
        except model.DoesNotExist:
            raise exceptions.AuthenticationFailed(_('Invalid token.'))
        if not token.user.is_active:
            raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))

        print("token.created",token.created)        

		# TOKEN_LIFETIME=1  ,在settings.py 中定义,表示该token能维持一天
        if timezone.now() > (token.created + timedelta(days=settings.TOKEN_LIFETIME)):  # Token过期验证
            raise exceptions.AuthenticationFailed(_('Token has expired'))

        return (token.user, token)

同时在项目的 settings.py 中配置 DEFAULT_AUTHENTICATION_CLASSES 即可:
settings.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.ExpiringTokenAuthentication',
    ),
}

这样就保证了 Token 的有效期是 TOKEN_LIFETIME。调用方如果想为了避免每次请求都去调用上篇提到的
url = ‘http://192.168.56.101:8080/drf_token/’ 去获取token, 可以在获取 Token 后,可以把 Token 放在自己的缓存里,然后当发送业务请求的时候,把 Token 封装到请求头里即可。当然需要处理 Token 失效的异常。

你可能感兴趣的:(Django,#,auth)