滑动续期与自动刷新:

Web:访问令牌 10 分钟;活跃时自动轮换刷新令牌;连续无操作 30 分钟后清除登录并跳转登录页。
App:会话窗口 3 天;打开 App、恢复前台或请求接口时自动刷新并重新顺延 3 天。
普通登录和 SSO 使用同一策略。
刷新令牌只以 SHA-256 摘要入库,每次刷新都会轮换,旧令牌无法再次使用;退出登录会吊销刷新令牌。
网络临时故障不会误清登录状态,多标签页同时刷新也做了竞争处理。
This commit is contained in:
2026-08-03 19:20:39 +08:00 Unverified
parent 6bee29a351
commit 5ec62a03ca
24 changed files with 6986 additions and 75 deletions
@@ -78,6 +78,8 @@ public sealed class DevelopmentSqliteMigrator(
"20260729_41_app_update_releases";
private const string IntegratedExperimentSchedulingMigration =
"20260802_42_integrated_experiment_scheduling";
private const string RefreshSessionsMigration =
"20260803_43_refresh_sessions";
public async Task MigrateAsync(CancellationToken cancellationToken = default)
{
@@ -593,6 +595,10 @@ public sealed class DevelopmentSqliteMigrator(
? []
: IntegratedExperimentSchedulingStatements,
cancellationToken);
await ApplyMigrationAsync(
RefreshSessionsMigration,
RefreshSessionsStatements,
cancellationToken);
}
private async Task ApplyMigrationAsync(
@@ -2104,6 +2110,34 @@ public sealed class DevelopmentSqliteMigrator(
"""
];
private static readonly string[] RefreshSessionsStatements =
[
"""
CREATE TABLE IF NOT EXISTS "RefreshSessions" (
"Id" TEXT NOT NULL CONSTRAINT "PK_RefreshSessions" PRIMARY KEY,
"UserId" TEXT NOT NULL,
"TokenHash" TEXT NOT NULL,
"ClientType" TEXT NOT NULL,
"SecurityStamp" TEXT NOT NULL,
"ExpiresAt" TEXT NOT NULL,
"CreatedAt" TEXT NOT NULL,
"LastRefreshedAt" TEXT NOT NULL,
"RevokedAt" TEXT NULL,
"ReplacedBySessionId" TEXT NULL,
CONSTRAINT "FK_RefreshSessions_AspNetUsers_UserId"
FOREIGN KEY ("UserId") REFERENCES "AspNetUsers" ("Id") ON DELETE CASCADE
);
""",
"""
CREATE UNIQUE INDEX IF NOT EXISTS "IX_RefreshSessions_TokenHash"
ON "RefreshSessions" ("TokenHash");
""",
"""
CREATE INDEX IF NOT EXISTS "IX_RefreshSessions_UserId_ExpiresAt"
ON "RefreshSessions" ("UserId", "ExpiresAt");
"""
];
private static readonly string[] ApprovalTableStatements =
[
"""CREATE TABLE "CourseExemptions" ("Id" TEXT NOT NULL CONSTRAINT "PK_CourseExemptions" PRIMARY KEY, "StudentId" TEXT NOT NULL, "TeachingTaskId" TEXT NOT NULL, "Reason" TEXT NOT NULL, "Status" INTEGER NOT NULL, "ReviewComment" TEXT NULL, "SubmittedAt" TEXT NOT NULL, "ReviewedAt" TEXT NULL, "ReviewedByUserId" TEXT NULL, "CreatedAt" TEXT NOT NULL, "UpdatedAt" TEXT NOT NULL, CONSTRAINT "FK_CourseExemptions_Students" FOREIGN KEY ("StudentId") REFERENCES "Students" ("Id") ON DELETE RESTRICT, CONSTRAINT "FK_CourseExemptions_TeachingTasks" FOREIGN KEY ("TeachingTaskId") REFERENCES "TeachingTasks" ("Id") ON DELETE RESTRICT);""",