如何在ASP.NET Core 5中借助Identity实现两层独立身份认证授权?
方案可行性结论
ASP.NET Core Identity 完全支持你要求的两层独立认证授权架构,不需要做过度改造即可满足「第一层内存存储、第二层DB存储」的合规要求,两层逻辑完全隔离,可分别对应客户端自动接入、用户人工登录的流程。
落地实现步骤
第一层:客户端接入认证授权(内存存储)
- 不复用Identity默认的用户体系,基于ASP.NET Core多认证方案机制,单独注册一套客户端专属的认证方案,和第二层用户认证完全隔离:
// Program.cs 中注册客户端认证方案 builder.Services.AddAuthentication() // 单独注册客户端接入认证方案,不要和用户认证共用 .AddScheme<ClientAccessTokenAuthOptions, ClientAccessTokenAuthHandler>("ClientAccess", opt => { }); // 注册全局单例的客户端会话管理器,所有数据仅存内存 builder.Services.AddSingleton<IClientSessionManager, ClientSessionManager>();
- 客户端会话、在线计数全在内存中维护,自己实现
IClientSessionManager单例服务,内部用ConcurrentDictionary存储合法接入的客户端ID、角色、过期时间,用原子操作Interlocked统计在线数量,超过license阈值直接拒绝接入:
public class ClientSessionManager : IClientSessionManager { private readonly ConcurrentDictionary<string, ClientSession> _validSessions = new(); private int _onlineClientCount; // 按实际license额度配置 private const int LicenseUpperLimit = 500; public (bool IsAllowed, string AccessToken) TryCreateClientSession(ClientType clientType) { // 原子计数避免并发问题 if (Interlocked.Increment(ref _onlineClientCount) > LicenseUpperLimit) { Interlocked.Decrement(ref _onlineClientCount); return (false, string.Empty); } var accessToken = Guid.NewGuid().ToString("N"); _validSessions.TryAdd(accessToken, new ClientSession { ClientRole = clientType.ToString(), ExpireAt = DateTime.Now.AddHours(2) }); return (true, accessToken); } }
- 客户端角色校验直接用原生授权特性实现,需要客户端接入才能访问的接口直接标注
[Authorize(AuthenticationSchemes = "ClientAccess", Roles = "公众客户端,员工客户端,管理员客户端")],校验逻辑全在内存执行,不需要落库。 - 客户端认证通过后,将客户端角色存入Claim,后续第二层用户登录时可直接读取该Claim限制用户登录类型,符合你的业务规则要求。
第二层:用户身份认证授权(DB存储)
- 这一层直接用ASP.NET Core Identity原生实现即可,注册默认的
IdentityUser、IdentityRole体系,配置EF Core关联业务DB,密码哈希、角色校验、登录态管理等能力直接复用原生功能,不需要额外改造:
// Program.cs 中注册Identity用户认证 builder.Services.AddDbContext<ApplicationDbContext>(opt => opt.UseSqlServer(builder.Configuration.GetConnectionString("Default"))); builder.Services.AddIdentityCore<IdentityUser>(opt => { }) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>();
- 接口授权可配置双认证方案校验,业务接口要求同时通过客户端接入认证和用户认证才能访问:
// 全局授权策略配置 builder.Services.AddAuthorization(opt => { opt.AddPolicy("BizAccess", policy => { policy.AddAuthenticationSchemes("ClientAccess", IdentityConstants.ApplicationScheme); policy.RequireAuthenticatedUser(); }); }); // 业务接口直接加特性即可 [Authorize(Policy = "BizAccess")] public class OrderController : ControllerBase {}
- 用户登录逻辑中新增客户端角色校验:用户提交登录请求时,先从第一层认证的Claims中读取当前客户端角色,比如客户端是公众客户端时仅允许公众用户账号登录,是员工客户端时仅允许员工账号登录,不符合要求直接返回登录失败。
核心注意事项
- 第一层给客户端返回的AccessToken要设置过期时间,配套后台定时任务(
IHostedService)定期清理过期的客户端会话,同步扣减在线计数,避免客户端异常退出导致license额度被占满。 - 第一层的所有会话数据不要写入任何持久化存储,包括日志、分布式缓存,完全限定在服务端进程内存中,满足你的安全要求。
- 客户端凭证不要硬编码,每次接入成功下发临时AccessToken,避免凭证泄露被恶意复用。
内容的提问来源于stack exchange,提问作者Sam Carleton
相关产品推荐
相关产品推荐

