| 123456789101112131415161718192021222324252627282930313233343536373839404142434445 |
- """sys_user 加 session_jti 列(一次一码防重放,安全需求)。
- Revision ID: 0038_session_jti
- Revises: 0037_drop_audit_target_check
- Create Date: 2026-09-17
- 变更要点:
- 1. sys_user 加 session_jti:当前有效会话的授权码代(JWT jti)——写操作成功后
- 轮换出新码并在响应头返回,旧码写操作即拒(SESSION_ROTATED);
- 2. 读操作不比对(REST 读重放无危害,轮询与写并发时在途 GET 不掉线);
- 3. 兼容:NULL = 未纳管(存量会话 / 轮换开关关闭期间登录),校验跳过;
- 4. 双引擎幂等:先探测列存在再加(MySQL 与达梦升级互不冲突)。
- """
- from __future__ import annotations
- from collections.abc import Sequence
- import sqlalchemy as sa
- from alembic import op
- revision: str = "0038_session_jti"
- down_revision: str | None = "0037_drop_audit_target_check"
- branch_labels: str | Sequence[str] | None = None
- depends_on: str | Sequence[str] | None = None
- def _column_exists(table: str, column: str) -> bool:
- # 达梦 inspector 返回大写名,统一小写比较
- inspector = sa.inspect(op.get_bind())
- return column.lower() in {
- name.lower() for name in inspector.get_columns(table)
- }
- def upgrade() -> None:
- if _column_exists("sys_user", "session_jti"):
- return
- op.add_column("sys_user", sa.Column("session_jti", sa.String(length=64), nullable=True))
- def downgrade() -> None:
- if not _column_exists("sys_user", "session_jti"):
- return
- op.drop_column("sys_user", "session_jti")
|