上篇我们介绍了 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 失效的异常。