security(jwt): 收敛 token 生命周期(168h→24h)并启用 refresh 轮换黑名单
- ACCESS_TOKEN_LIFETIME 默认 24h(缩小泄露窗口) - BLACKLIST_AFTER_ROTATION 默认开启,注册 token_blacklist app - LOGGING 增加 RotatingFileHandler 落盘(django.log) - USE_TZ=False 决策文档化(存量 naive UTC 时间戳无法安全切换)
This commit is contained in:
1 parent
67c4d03597
commit
e76a5b359e
1 file changed
+15
-3
+15
-3
@@ -50,6 +50,7 @@ INSTALLED_APPS = _app_getlist('apps', 'INSTALLED_APPS', fallback=[
|
||||
'django.contrib.staticfiles',
|
||||
'rest_framework',
|
||||
'rest_framework_simplejwt',
|
||||
'rest_framework_simplejwt.token_blacklist', # refresh 轮换后旧 token 拉黑(BLACKLIST_AFTER_ROTATION)
|
||||
'corsheaders',
|
||||
'gvsds.apps.core',
|
||||
'gvsds.apps.gerp',
|
||||
@@ -235,6 +236,9 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||
LANGUAGE_CODE = _app_get('server', 'LANGUAGE_CODE', fallback='zh-hans')
|
||||
TIME_ZONE = _app_get('server', 'TIME_ZONE', fallback='Asia/Shanghai')
|
||||
USE_I18N = _app_getbool('server', 'USE_I18N', fallback=True)
|
||||
# USE_TZ 保持 False:全项目时间戳以 datetime.utcnow() 存 naive UTC,
|
||||
# 改 True 会把存量 naive 时间解释为本地时区,导致 stats 周期键/跨时区比较错乱。
|
||||
# 若未来统一时区,需先迁移存量数据为 aware UTC(见架构债治理清单 2.7)。
|
||||
USE_TZ = _app_getbool('server', 'USE_TZ', fallback=False)
|
||||
|
||||
STATIC_URL = _app_get('static', 'STATIC_URL', fallback='/static/')
|
||||
@@ -288,10 +292,10 @@ REST_FRAMEWORK = {
|
||||
}
|
||||
|
||||
SIMPLE_JWT = {
|
||||
'ACCESS_TOKEN_LIFETIME': timedelta(hours=_app_getint('jwt', 'ACCESS_TOKEN_LIFETIME_HOURS', fallback=168)), # 7 天
|
||||
'ACCESS_TOKEN_LIFETIME': timedelta(hours=_app_getint('jwt', 'ACCESS_TOKEN_LIFETIME_HOURS', fallback=24)), # 24 小时(收敛自 168h,缩小泄露窗口)
|
||||
'REFRESH_TOKEN_LIFETIME': timedelta(days=_app_getint('jwt', 'REFRESH_TOKEN_LIFETIME_DAYS', fallback=90)), # 90 天
|
||||
'ROTATE_REFRESH_TOKENS': _app_getbool('jwt', 'ROTATE_REFRESH_TOKENS', fallback=True),
|
||||
'BLACKLIST_AFTER_ROTATION': _app_getbool('jwt', 'BLACKLIST_AFTER_ROTATION', fallback=False),
|
||||
'BLACKLIST_AFTER_ROTATION': _app_getbool('jwt', 'BLACKLIST_AFTER_ROTATION', fallback=True), # 轮换后旧 refresh 立即失效
|
||||
'AUTH_HEADER_TYPES': tuple(_app_getlist('jwt', 'AUTH_HEADER_TYPES', fallback=['Bearer'])),
|
||||
'USER_ID_FIELD': 'UserUUID',
|
||||
'USER_ID_CLAIM': 'UserUUID',
|
||||
@@ -330,9 +334,17 @@ LOGGING = {
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'verbose',
|
||||
},
|
||||
'file': {
|
||||
'class': 'logging.handlers.RotatingFileHandler',
|
||||
'filename': str(BASE_DIR / 'logs' / 'django.log'),
|
||||
'maxBytes': 10 * 1024 * 1024,
|
||||
'backupCount': 5,
|
||||
'formatter': 'verbose',
|
||||
'encoding': 'utf-8',
|
||||
},
|
||||
},
|
||||
'root': {
|
||||
'handlers': ['console'],
|
||||
'handlers': ['console', 'file'],
|
||||
'level': _app_get('logging', 'LEVEL', fallback='INFO'),
|
||||
},
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user