init medical training project
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import logging
|
||||
|
||||
from django.core.cache import cache
|
||||
from rest_framework.exceptions import APIException
|
||||
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||||
from rest_framework_simplejwt.exceptions import InvalidToken
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_REVOKED = {'code': 'AUTH_TOKEN_REVOKED', 'message': 'token已被吊销,请重新登录'}
|
||||
_INVALIDATED = {'code': 'AUTH_TOKEN_INVALIDATED', 'message': 'token已失效,请重新登录'}
|
||||
_REDIS_DOWN = {'code': 'SYS_DEPENDENCY_DOWN', 'message': 'Redis服务不可用'}
|
||||
|
||||
|
||||
class RedisBlacklistJWTAuthentication(JWTAuthentication):
|
||||
"""在 simplejwt 校验通过后追加 Redis 黑名单检查。"""
|
||||
|
||||
def get_validated_token(self, raw_token):
|
||||
token = super().get_validated_token(raw_token)
|
||||
try:
|
||||
jti = token.payload.get('jti')
|
||||
uid = token.payload.get('user_id')
|
||||
iat = token.payload.get('iat')
|
||||
|
||||
if jti and cache.get(f'jwt_blacklist:{jti}'):
|
||||
raise InvalidToken(_REVOKED)
|
||||
|
||||
if uid and iat is not None:
|
||||
invalid_before = cache.get(f'jwt_user_invalid_before:{uid}')
|
||||
if invalid_before is not None and iat < int(invalid_before):
|
||||
raise InvalidToken(_INVALIDATED)
|
||||
|
||||
except InvalidToken:
|
||||
raise
|
||||
except Exception as e:
|
||||
# fail-closed:Redis 不可用时拒绝请求(安全 > 可用)
|
||||
logger.error('Redis error during JWT blacklist check: %s', e)
|
||||
ex = APIException()
|
||||
ex.status_code = 503
|
||||
ex.detail = _REDIS_DOWN
|
||||
raise ex
|
||||
|
||||
return token
|
||||
Reference in New Issue
Block a user