19 KiB
会话管理
**本文档引用的文件** - [IdentitySessionManager.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IdentitySessionManager.cs) - [IdentitySessionStore.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IdentitySessionStore.cs) - [IIdentitySessionStore.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IIdentitySessionStore.cs) - [IIdentitySessionManager.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IIdentitySessionManager.cs) - [IdentitySessionAppService.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/IdentitySessionAppService.cs) - [IdentitySessionController.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.HttpApi/LINGYUN/Abp/Identity/IdentitySessionController.cs) - [IdentitySessionDto.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/IdentitySessionDto.cs) - [EfCoreIdentitySessionRepository.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.EntityFrameworkCore/LINGYUN/Abp/Identity/EntityFrameworkCore/EfCoreIdentitySessionRepository.cs) - [IdentitySessionCleanupBackgroundWorker.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IdentitySessionCleanupBackgroundWorker.cs) - [IdentitySessionCheckOptions.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Session/LINGYUN/Abp/Identity/Session/IdentitySessionCheckOptions.cs) - [DefaultIdentitySessionChecker.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Session/LINGYUN/Abp/Identity\Session/DefaultIdentitySessionChecker.cs) - [IdentitySessionCacheItem.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Session/LINGYUN/Abp/Identity/Session/IdentitySessionCacheItem.cs) - [IdentitySessionEto.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IdentitySessionEto.cs) - [DeviceInfo.cs](file://aspnet-core/modules/identity/LINGYUN.Abp.Identity.Session/LINGYUN/Abp/Identity/Session/DeviceInfo.cs)目录
简介
会话管理系统是 abp-next-admin 项目中身份管理模块的核心组成部分,负责管理用户的会话生命周期。该系统提供了完整的会话跟踪、验证和管理功能,支持多设备登录、会话撤销、自动清理等高级特性。
会话管理系统采用分层架构设计,包含领域服务、应用服务、数据访问层和缓存层,确保了系统的可扩展性和高性能。系统支持分布式环境下的会话同步,并提供了完善的安全机制来保护用户会话。
项目结构
会话管理模块在项目中的组织结构如下:
graph TB
subgraph "会话管理模块结构"
A[IdentitySessionManager<br/>会话管理器] --> B[IdentitySessionStore<br/>会话存储]
A --> C[IIdentitySessionCache<br/>会话缓存]
A --> D[IdentitySessionCheckOptions<br/>会话检查选项]
E[IdentitySessionAppService<br/>会话应用服务] --> A
F[IdentitySessionController<br/>会话控制器] --> E
G[EfCoreIdentitySessionRepository<br/>EFCore仓储] --> H[数据库]
I[IdentitySessionCleanupBackgroundWorker<br/>会话清理后台任务] --> A
J[DefaultIdentitySessionChecker<br/>默认会话检查器] --> A
end
图表来源
- IdentitySessionManager.cs
- IdentitySessionStore.cs
章节来源
- IdentitySessionManager.cs
- IdentitySessionStore.cs
核心组件
会话管理系统的核心组件包括以下关键部分:
1. 会话管理器 (IdentitySessionManager)
负责会话的创建、更新和撤销操作,是整个会话管理的核心协调者。
2. 会话存储 (IdentitySessionStore)
提供会话数据的持久化存储功能,支持会话的增删改查操作。
3. 应用服务 (IdentitySessionAppService)
提供会话管理的业务逻辑封装,作为API层与领域层之间的桥梁。
4. 数据访问层 (EfCoreIdentitySessionRepository)
基于EntityFrameworkCore实现的会话数据访问层,负责与数据库的交互。
5. 缓存层 (IdentitySessionCache)
提供会话数据的内存缓存,提高会话验证和查询的性能。
章节来源
- IdentitySessionManager.cs
- IdentitySessionStore.cs
架构概览
会话管理系统采用经典的分层架构模式,各层职责明确,耦合度低:
graph LR
subgraph "表现层"
A[IdentitySessionController]
end
subgraph "应用层"
B[IdentitySessionAppService]
end
subgraph "领域层"
C[IdentitySessionManager]
D[IdentitySessionStore]
E[IdentitySessionChecker]
end
subgraph "基础设施层"
F[IdentitySessionCache]
G[EfCoreIdentitySessionRepository]
H[BackgroundWorker]
end
subgraph "数据层"
I[(数据库)]
end
A --> B
B --> C
C --> D
C --> F
D --> G
G --> I
C --> E
H --> C
图表来源
- IdentitySessionController.cs
- IdentitySessionAppService.cs
详细组件分析
会话管理器 (IdentitySessionManager)
会话管理器是会话管理系统的核心组件,负责协调各个子系统的工作:
classDiagram
class IdentitySessionManager {
+IDeviceInfoProvider DeviceInfoProvider
+IIdentitySessionCache IdentitySessionCache
+IIdentitySessionStore IdentitySessionStore
+IdentityDynamicClaimsPrincipalContributorCache IdentityDynamicClaimsPrincipalContributorCache
+SaveSessionAsync(ClaimsPrincipal, CancellationToken) Task
+RevokeSessionAsync(string, CancellationToken) Task
}
class IIdentitySessionManager {
<<interface>>
+SaveSessionAsync(ClaimsPrincipal, CancellationToken) Task
+RevokeSessionAsync(string, CancellationToken) Task
}
class IdentitySessionStore {
+CreateAsync(...) Task~IdentitySession~
+UpdateAsync(IdentitySession, CancellationToken) Task
+GetAsync(string, CancellationToken) Task~IdentitySession~
+FindAsync(string, CancellationToken) Task~IdentitySession~
+ExistAsync(string, CancellationToken) Task~bool~
+RevokeAsync(string, CancellationToken) Task
}
class IIdentitySessionCache {
<<interface>>
+RefreshAsync(string, IdentitySessionCacheItem, CancellationToken) Task
+GetAsync(string, CancellationToken) Task~IdentitySessionCacheItem~
+RemoveAsync(string, CancellationToken) Task
}
IdentitySessionManager ..|> IIdentitySessionManager
IdentitySessionManager --> IdentitySessionStore
IdentitySessionManager --> IIdentitySessionCache
图表来源
- IdentitySessionManager.cs
- IIdentitySessionManager.cs
会话保存流程
会话保存是一个复杂的异步流程,涉及多个步骤:
sequenceDiagram
participant Client as 客户端
participant Manager as IdentitySessionManager
participant Store as IdentitySessionStore
participant Cache as IdentitySessionCache
participant Provider as DeviceInfoProvider
Client->>Manager : SaveSessionAsync(claimsPrincipal)
Manager->>Provider : GetDeviceInfoAsync()
Provider-->>Manager : DeviceInfo
Manager->>Store : CreateAsync(sessionId, device, ...)
Store->>Store : InsertAsync(IdentitySession)
Store-->>Manager : IdentitySession
Manager->>Cache : RefreshAsync(sessionId, cacheItem)
Cache-->>Manager : 成功
Manager-->>Client : 完成
图表来源
- IdentitySessionManager.cs
章节来源
- IdentitySessionManager.cs
会话存储层 (IdentitySessionStore)
会话存储层负责会话数据的持久化操作:
classDiagram
class IdentitySessionStore {
+ICurrentUser CurrentUser
+IGuidGenerator GuidGenerator
+IIdentitySessionRepository IdentitySessionRepository
+CreateAsync(...) Task~IdentitySession~
+UpdateAsync(IdentitySession, CancellationToken) Task
+GetAsync(Guid, CancellationToken) Task~IdentitySession~
+FindAsync(Guid, CancellationToken) Task~IdentitySession~
+GetAsync(string, CancellationToken) Task~IdentitySession~
+FindAsync(string, CancellationToken) Task~IdentitySession~
+FindLastAsync(Guid, string, CancellationToken) Task~IdentitySession~
+ExistAsync(string, CancellationToken) Task~bool~
+RevokeAsync(Guid, CancellationToken) Task
+RevokeAsync(string, CancellationToken) Task
+RevokeAllAsync(Guid, Guid?, CancellationToken) Task
+RevokeAllAsync(Guid, string, Guid?, CancellationToken) Task
+RevokeAllAsync(TimeSpan, CancellationToken) Task
}
class IIdentitySessionStore {
<<interface>>
+CreateAsync(...) Task~IdentitySession~
+UpdateAsync(IdentitySession, CancellationToken) Task
+GetAsync(Guid, CancellationToken) Task~IdentitySession~
+FindAsync(Guid, CancellationToken) Task~IdentitySession~
+GetAsync(string, CancellationToken) Task~IdentitySession~
+FindAsync(string, CancellationToken) Task~IdentitySession~
+FindLastAsync(Guid, string, CancellationToken) Task~IdentitySession~
+ExistAsync(string, CancellationToken) Task~bool~
+RevokeAsync(Guid, CancellationToken) Task
+RevokeAsync(string, CancellationToken) Task
}
IdentitySessionStore ..|> IIdentitySessionStore
图表来源
- IdentitySessionStore.cs
- IIdentitySessionStore.cs
章节来源
- IdentitySessionStore.cs
会话数据传输对象 (IdentitySessionDto)
会话数据传输对象用于在不同层之间传递会话信息:
classDiagram
class IdentitySessionDto {
+Guid Id
+string SessionId
+string Device
+string DeviceInfo
+Guid UserId
+string ClientId
+string IpAddresses
+DateTime SignedIn
+DateTime? LastAccessed
}
class EntityDto~Guid~ {
<<abstract>>
+Guid Id
}
IdentitySessionDto --|> EntityDto~Guid~
图表来源
- IdentitySessionDto.cs
章节来源
- IdentitySessionDto.cs
会话清理后台任务
会话清理后台任务负责定期清理过期的会话数据:
flowchart TD
A[后台任务启动] --> B{是否启用清理?}
B --> |否| C[结束任务]
B --> |是| D[获取分布式锁]
D --> E{获取成功?}
E --> |否| F[记录日志并结束]
E --> |是| G[执行清理操作]
G --> H[删除过期会话]
H --> I[释放分布式锁]
I --> J[记录清理结果]
J --> K[等待下次执行]
K --> A
图表来源
- IdentitySessionCleanupBackgroundWorker.cs
章节来源
- IdentitySessionCleanupBackgroundWorker.cs
会话检查器 (IdentitySessionChecker)
会话检查器负责验证会话的有效性:
classDiagram
class IIdentitySessionChecker {
<<interface>>
+ValidateSessionAsync(ClaimsPrincipal, CancellationToken) Task~bool~
}
class DefaultIdentitySessionChecker {
+IClock Clock
+ICurrentTenant CurrentTenant
+IDeviceInfoProvider DeviceInfoProvider
+IDistributedEventBus DistributedEventBus
+IIdentitySessionCache IdentitySessionCache
+IdentitySessionCheckOptions SessionCheckOptions
+ValidateSessionAsync(ClaimsPrincipal, CancellationToken) Task~bool~
}
class AllowAnonymousIdentitySessionChecker {
+ValidateSessionAsync(ClaimsPrincipal, CancellationToken) Task~bool~
}
IIdentitySessionChecker <|.. DefaultIdentitySessionChecker
IIdentitySessionChecker <|.. AllowAnonymousIdentitySessionChecker
图表来源
- IIdentitySessionChecker.cs
- DefaultIdentitySessionChecker.cs
章节来源
- DefaultIdentitySessionChecker.cs
依赖关系分析
会话管理系统的依赖关系复杂但清晰:
graph TB
subgraph "外部依赖"
A[Microsoft.Extensions.DependencyInjection]
B[Volo.Abp.Identity]
C[EntityFrameworkCore]
end
subgraph "内部模块"
D[IdentitySessionManager]
E[IdentitySessionStore]
F[IdentitySessionAppService]
G[IdentitySessionController]
H[IdentitySessionCleanupBackgroundWorker]
end
subgraph "基础设施"
I[IdentitySessionCache]
J[DeviceInfoProvider]
K[DistributedEventBus]
end
A --> D
A --> E
A --> F
A --> G
A --> H
B --> D
B --> E
B --> F
C --> E
D --> I
D --> J
D --> K
E --> F
F --> G
图表来源
- IdentitySessionManager.cs
- IdentitySessionStore.cs
章节来源
- IdentitySessionManager.cs
- IdentitySessionStore.cs
性能考虑
会话管理系统在设计时充分考虑了性能优化:
1. 缓存策略
- 使用内存缓存存储活跃会话信息
- 支持分布式缓存以适应集群环境
- 提供缓存预热和失效机制
2. 数据库优化
- 为会话表建立适当的索引
- 支持多种数据库引擎(MySQL、SQL Server、PostgreSQL)
- 提供批量操作支持
3. 异步处理
- 所有I/O操作均采用异步模式
- 后台任务处理非实时操作
- 避免阻塞主线程
4. 资源管理
- 合理使用连接池
- 及时释放数据库连接
- 避免内存泄漏
故障排除指南
常见问题及解决方案
1. 会话创建失败
症状: 用户登录后无法创建会话 原因:
- 设备信息提供程序异常
- 数据库连接问题
- 会话ID冲突
解决方案:
// 检查设备信息提供程序配置
var deviceInfo = await DeviceInfoProvider.GetDeviceInfoAsync();
if (deviceInfo == null)
{
throw new InvalidOperationException("设备信息提供程序返回null");
}
// 检查数据库连接
try
{
await IdentitySessionStore.CreateAsync(...);
}
catch (Exception ex)
{
Logger.LogError(ex, "会话创建失败");
// 实施重试机制或降级策略
}
2. 会话验证失败
症状: 用户请求被拒绝,提示会话无效 原因:
- 缓存数据过期
- 分布式锁竞争
- 时间同步问题
解决方案:
// 检查会话缓存状态
var cacheItem = await IdentitySessionCache.GetAsync(sessionId);
if (cacheItem == null)
{
// 尝试从数据库重新加载
var session = await IdentitySessionStore.FindAsync(sessionId);
if (session != null)
{
await RefreshSessionCache(session);
}
}
3. 清理任务异常
症状: 后台清理任务频繁失败 原因:
- 分布式锁获取失败
- 数据库锁定超时
- 事务冲突
解决方案:
// 增加重试机制
var retryCount = 3;
while (retryCount > 0)
{
try
{
await IdentitySessionStore.RevokeAllAsync(inactiveTimeSpan);
break;
}
catch (Exception ex)
{
retryCount--;
if (retryCount == 0)
{
Logger.LogError(ex, "会话清理任务连续失败");
throw;
}
await Task.Delay(TimeSpan.FromSeconds(5));
}
}
章节来源
- IdentitySessionManager.cs
- IdentitySessionCleanupBackgroundWorker.cs
结论
会话管理系统是 abp-next-admin 项目中一个设计精良、功能完备的身份管理组件。它通过分层架构、异步处理和缓存优化,提供了高性能的会话管理能力。
主要优势
- 架构清晰: 分层设计使得系统易于维护和扩展
- 性能优异: 多级缓存和异步处理保证了高并发性能
- 功能完整: 支持会话创建、验证、撤销和清理等全生命周期管理
- 安全可靠: 分布式锁和事务管理确保了数据一致性
- 易于集成: 提供了丰富的API和配置选项
最佳实践建议
- 合理配置缓存: 根据业务需求调整缓存大小和过期时间
- 监控系统健康: 定期检查会话清理任务和缓存命中率
- 优化数据库: 为会话表建立合适的索引以提高查询性能
- 实施监控: 添加适当的日志记录和指标收集
- 定期维护: 清理过期会话数据,避免数据库膨胀
通过遵循这些最佳实践,可以确保会话管理系统在生产环境中稳定高效地运行。