DjangoRestFramework_JWT 忽略自定义中的负载 payload_handler
DjangoRestFramework_JWT ignoring payload in custom payload_handler
我为 jwt 创建了这个自定义 jwt_payload_handler,以便它可以识别密码。如果用户更改密码,我希望以前的令牌过期。但是即使我有一个自定义处理程序,由于某种原因 drf jwt 会忽略这些更改,并且在我更改用户密码或更改 password_last_change 字符串值后仍然接受过去的令牌。
我是否缺少其他配置?
jwt_payload_handler:
def jwt_payload_handler(user):
username_field = get_username_field()
username = get_username(user)
password_last_change = user.password_last_change # getting json not serializable error. constant string for now
warnings.warn(
'The following fields will be removed in the future: '
'`email` and `user_id`. ',
DeprecationWarning
)
payload = {
'user_id': user.pk,
'username': username,
'password': user.password,
'exp': (datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA) ,
'password_last_change': 'test1',
}
if hasattr(user, 'email'):
payload['email'] = user.email
if isinstance(user.pk, uuid.UUID):
payload['user_id'] = str(user.pk)
payload[username_field] = username
# Include original issued at time for a brand new token,
# to allow token refresh
if api_settings.JWT_ALLOW_REFRESH:
payload['orig_iat'] = timegm(
datetime.utcnow().utctimetuple()
)
if api_settings.JWT_AUDIENCE is not None:
payload['aud'] = api_settings.JWT_AUDIENCE
if api_settings.JWT_ISSUER is not None:
payload['iss'] = api_settings.JWT_ISSUER
return payload
我明白了。我们需要在 settings.py 文件中设置 JWT_GET_USER_SECRET_KEY
值,而不是自定义 jwt_payload_handler 函数。默认情况下它是 None 但它接受一个将用户作为参数的函数和 returns 一个 uuid 字符串。如果未配置,conf django 密钥将用于所有用户。但是如果设置了,每个用户都会有自己的密钥。
更改密码时,同时更新 uuid。
在用户模型中,我们可以将一些字段设置为:
class TestUser(AbstractBaseUser):
jwt_secret = models.UUIDField(default=uuid.uuid4)
函数示例:
def jwt_get_secret_key(user_model):
return user_model.jwt_secret
在设置中:
JWT_AUTH = {
...
'JWT_GET_USER_SECRET_KEY': 'path.to.jwt_get_secret_key'
...
}
因此在您的视图或信号中,在调用 set_password 方法之后:
您可以将 user.secret_jwt 设置为新值:
user.secret_jwt = uuid.uuid4()
user.save()
这将使之前的所有请求都无效。
我为 jwt 创建了这个自定义 jwt_payload_handler,以便它可以识别密码。如果用户更改密码,我希望以前的令牌过期。但是即使我有一个自定义处理程序,由于某种原因 drf jwt 会忽略这些更改,并且在我更改用户密码或更改 password_last_change 字符串值后仍然接受过去的令牌。
我是否缺少其他配置?
jwt_payload_handler:
def jwt_payload_handler(user):
username_field = get_username_field()
username = get_username(user)
password_last_change = user.password_last_change # getting json not serializable error. constant string for now
warnings.warn(
'The following fields will be removed in the future: '
'`email` and `user_id`. ',
DeprecationWarning
)
payload = {
'user_id': user.pk,
'username': username,
'password': user.password,
'exp': (datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA) ,
'password_last_change': 'test1',
}
if hasattr(user, 'email'):
payload['email'] = user.email
if isinstance(user.pk, uuid.UUID):
payload['user_id'] = str(user.pk)
payload[username_field] = username
# Include original issued at time for a brand new token,
# to allow token refresh
if api_settings.JWT_ALLOW_REFRESH:
payload['orig_iat'] = timegm(
datetime.utcnow().utctimetuple()
)
if api_settings.JWT_AUDIENCE is not None:
payload['aud'] = api_settings.JWT_AUDIENCE
if api_settings.JWT_ISSUER is not None:
payload['iss'] = api_settings.JWT_ISSUER
return payload
我明白了。我们需要在 settings.py 文件中设置 JWT_GET_USER_SECRET_KEY
值,而不是自定义 jwt_payload_handler 函数。默认情况下它是 None 但它接受一个将用户作为参数的函数和 returns 一个 uuid 字符串。如果未配置,conf django 密钥将用于所有用户。但是如果设置了,每个用户都会有自己的密钥。
更改密码时,同时更新 uuid。
在用户模型中,我们可以将一些字段设置为:
class TestUser(AbstractBaseUser):
jwt_secret = models.UUIDField(default=uuid.uuid4)
函数示例:
def jwt_get_secret_key(user_model):
return user_model.jwt_secret
在设置中:
JWT_AUTH = {
...
'JWT_GET_USER_SECRET_KEY': 'path.to.jwt_get_secret_key'
...
}
因此在您的视图或信号中,在调用 set_password 方法之后: 您可以将 user.secret_jwt 设置为新值:
user.secret_jwt = uuid.uuid4()
user.save()
这将使之前的所有请求都无效。