导读
jwt在业界已经广泛使用,但这篇文章不是用来介绍jwt的,也不是用来介绍rest_framework_jwt的,而是跟各位掰扯掰扯rest_framework_jwt中的refresh token功能,因为它很可能不是你想象中的refresh token哦 。
场景再现
在jwt鉴权过程中往往会使用accesstoken 和 refreshtoken,顾名思义,refreshtoken是用来更新后的token,如果项目中配置了refreshtoken过期时间一般就是指refreshtoken的有效期,而且这个有效期比accesstoken的有效期要长得多。这个是一般场景中的释义,但是近期在用rest_framewrok_jwt对django项目进行鉴权的时候发现rest_framewrok_jwt 中refresh token的有效期完全不是这个意思。
大家都知道在django settings当中 ‘JWT_REFRESH_EXPIRATION_DELTA’: datetime.timedelta(days=1) 用来配置refresh token的有效期,很多人默认refresh token的有效期就是1天。如果将token有效期设置为’JWT_EXPIRATION_DELTA’: datetime.timedelta(seconds=60),当前同时生成token和refreshtoken 去试试他们的有效时间。你得到的结果应该是refreshtoken刚过60s refreshtoken就无效了,而且不能刷新token,这是为什么呢?其实JWT_REFRESH_EXPIRATION_DELTA的真正意思是token能被refresh的有效期而不是refresh token的有效期,也就是说你在JWT_REFRESH_EXPIRATION_DELTA设置的时间内可以去refresh token,过了这个时间就不能refresh token了,而refresh出来的token的有效期实际上跟access token是同一个时间,没错,就是60s。
下面我们就来通过源码证实一下。
源码佐证
refresh token的源码:
path: rest_framework_jwt.serializers.RefreshJSONWebTokenSerializer
class RefreshJSONWebTokenSerializer(VerificationBaseSerializer):
"""
Refresh an access token.
"""
def validate(self, attrs):
token = attrs['token']
# 这一段用来对需要进行refresh的代码进行校验
payload = self._check_payload(token=token)
user = self._check_user(payload=payload)
# Get and check 'orig_iat'
orig_iat = payload.get('orig_iat')
if orig_iat:
# Verify expiration
refresh_limit = api_settings.JWT_REFRESH_EXPIRATION_DELTA
if isinstance(refresh_limit, timedelta):
refresh_limit = (refresh_limit.days * 24 * 3600 +
refresh_limit.seconds)
expiration_timestamp = orig_iat + int(refresh_limit)
now_timestamp = timegm(datetime.utcnow().utctimetuple())
if now_timestamp > expiration_timestamp:
msg = _('Refresh has expired.')
raise serializers.ValidationError(msg)
else:
msg = _('orig_iat field is required.')
raise serializers.ValidationError(msg)
new_payload = jwt_payload_handler(user)
new_payload['orig_iat'] = orig_iat
return {
'token': jwt_encode_handler(new_payload),
'user': user
}
我们来看两个比较重要的函数
- payload = self._check_payload(token=token)
这个主要是来检查需要刷新的token,有一项检查就是当前token是否过期
serializers.py
def _check_payload(self, token