打算用这货来代替DRF自带的TokenAuth,原因是用JWT可以实现登录/注销功能。
然而它这两条默认设置让我摸不着头脑:
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
按照它文档所述:
JWT_EXPIRATION_DELTA
表示issue出去的token多久过期,默认是5mins;
JWT_REFRESH_EXPIRATION_DELTA
表示某个token被issue出去后,在多久间隔内可以用它来刷新以便获取新的token,默认是7天。它的原文描述长这样:(如果我理解有误,请告诉我,我的英文不太好)
Limit on token refresh, is a datetime.timedelta instance. This is how
much time after the original token that future tokens can be refreshed
from.Default is datetime.timedelta(days=7) (7 days).
根据这两个默认设置项,一个token被发布出去后,5分钟内便会过期,7天内可以用来刷新获得新token,似乎没啥子问题,然而问题来了,文档中关于Refresh Token一节明确说明:Note that only non-expired tokens will work. 于是实际情况就变成:一个token发布出去后,5分钟内可以用来刷新获得新token,5分钟后就不能用来刷新获得新token了(报HTTP 400错误)。天了噜,确定这个默认行为不是在开玩笑?你说那个7天的设置有什么卵用没?
显然不是我一个人觉得被坑了,请看这个讨论:
https://github.com/GetBlimp/django-rest-framework-jwt/issues/92#issuecomment-212846352
解决方案?
这个答案似乎有参考价值
追加更新:
经过不断测试和再三查看文档,上面的结论理解有误,更正如下:
JWT_REFRESH_EXPIRATION_DELTA
的确切含义是自从原始token被发布出去后,多长时间范围内它以及它的子孙token可以被用来刷新以获得新的子孙token
。
原始token,指的是通过用户名/密码验证后获得的token(即obtain_jwt_token
接口返回的token),原始token刷新后获得的token1,以及token1继续刷新获得的token2、token2再获得token3……形成了一串token链,这些token的过期时间都是JWT_EXPIRATION_DELTA
。
然而这串token链不可能一直无限制刷新下去,直到原始token发布后的JWT_REFRESH_EXPIRATION_DELTA
后,刷新操作将被终止,框架会返回HTTP 400。之后必须再次调用obtain_jwt_token
来获得新的原始token。
再回到5mins + 7days的默认设置上来,客户端首先调用obtain_jwt_token
进行登录操作,之后必须每隔小于5分钟就刷新一次token,才能保证不掉线。然而即使一直保持在线,上限也只有7天,7天过后必须重新登录,这才是5mins + 7days的确切含义。
显而易见,这种默认策略如果用在手机客户端上,是很不合适的。客户端如果置后台超过5分钟,再回去就得重新登录;就算一直在前台,连续用7天后还是得重新登录。也难怪乎那么多人会无法理解这一组设置的真正用意了。
我目前在客户端上准备采用30days + 360days的做法,只要一个月内使用一次app,就不用重新登录,最长可以一年不用重新登录。