You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 5.0 Razor Pages应用Identity框架并发登录用户识别异常

问题排查与解决

根因说明

你的问题本质是请求级的用户上下文被存储到了全局共享的对象中,并发请求时不同用户的上下文互相覆盖,就会出现串号现象;而单用户刷新页面时没有并发冲突,上下文读取正确,所以展示恢复正常。ASP.NET Core Identity 本身的默认实现完全支持多用户并发登录,不存在开箱即用的串号问题。

具体排查步骤

1. 优先检查你封装的两个身份工具类

这是最高概率的问题来源:

  • 如果工具类是静态类,且内部用静态字段/属性存储了ClaimsPrincipal User、User实体、SignInManager、UserManager这类和请求关联的对象,立刻移除所有相关静态存储。静态类的静态成员是全应用全局共享的,并发请求会同时修改同一个静态变量,必然出现互相覆盖的问题。
    解决方案:将静态工具类改为普通类,通过依赖注入注入到需要使用的PageModel或服务中,每次请求获取新的实例。
  • 如果工具类是注入服务,确认服务注册的生命周期为Scoped,即注册代码为:
    services.AddScoped<I你的工具类接口, 你的工具类实现>();
    // 无接口的情况用以下写法
    services.AddScoped<你的工具类>();
    
    绝对不能使用AddSingleton注册和请求上下文相关的服务,Singleton服务会在整个应用生命周期内只创建一个实例,所有请求共享,存储在成员变量中的用户上下文会被并发请求覆盖。

2. 检查PageModel及基类代码

检查所有Razor Pages PageModel,尤其是公共基类,有没有定义静态字段/属性存储当前用户信息,例如以下就是错误实现:

// 错误示例:静态变量全局共享,会被所有请求修改
public static User CurrentLoginUser { get; set; }

所有当前请求的用户信息,都应该每次使用时实时从User属性、UserManager.GetUserAsync(User)读取,不要缓存到静态变量中。

3. 检查Identity及DbContext的注册配置

确认你没有手动修改Identity相关服务、自定义MyDbContext的生命周期为Singleton:

  • 默认AddIdentity/AddDefaultIdentity注册的UserManager、SignInManager都是Scoped生命周期,不要手动更改。
  • 默认AddDbContext注册的MyDbContext是Scoped生命周期,如果你手动指定了ServiceLifetime.Singleton,请改回默认或显式指定ServiceLifetime.Scoped。

4. 检查IHttpContextAccessor的使用

如果你在服务中使用了IHttpContextAccessor获取当前用户,不要将HttpContext.User存储到单例服务的成员变量中,每次需要使用时实时读取:

// 正确示例:每次实时读取当前请求的用户
var userId = _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);

// 错误示例:单例服务中存储上下文会全局共享
private readonly ClaimsPrincipal _currentUser;
public 你的服务(IHttpContextAccessor accessor)
{
    _currentUser = accessor.HttpContext.User; // 构造函数中读取的是第一次实例化时的用户,后续所有请求都用这个值
}

内容的提问来源于stack exchange,提问作者bairog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 06:39:00