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

为何基类BaseApiController的ActiveUser属性值会异常?

问题原因及修复方案

核心问题:静态字段的线程安全隐患

你的BaseApiController中CurrentUser被声明为静态字段(public static User),静态成员属于类级别,所有控制器实例共享同一个CurrentUser对象。

在ASP.NET Web API的多请求并发场景下:

  • 数千用户的请求会同时被服务器处理,多个控制器实例(或同一控制器的不同请求实例)会同时修改这个静态字段。
  • 当请求A刚把CurrentUser设为用户X,请求B紧接着把它覆盖为用户Y,此时请求A后续操作读取ActiveUser.Id时,就会拿到用户Y的ID,导致日志错误关联用户。

修复方案

方案1:将静态字段改为实例字段

去掉CurrentUser的static修饰符,让每个控制器实例持有自己的用户信息:

public class BaseApiController : ApiController
{
    public User CurrentUser; // 移除static关键字
    public BaseApiController()
    {

    }

    protected override void Initialize(HttpControllerContext controllerContext)
    {
        base.Initialize(controllerContext);

        var request = controllerContext.Request;
        if (request.Headers.Authorization != null && request.Headers.Authorization.Scheme.Equals("bearer", StringComparison.OrdinalIgnoreCase))
        {
            CurrentUser = Helpers.JwtAuthentication.UserToken(request.Headers.Authorization.Parameter);
        }
    }

    protected User ActiveUser
    {
        get
        {
            return CurrentUser;
        }
    }
}

方案2:直接在属性中获取用户信息(无需字段存储)

如果JWT解析性能开销不大,也可以直接在ActiveUser属性中解析当前请求的用户,避免字段存储:

public class BaseApiController : ApiController
{
    protected override void Initialize(HttpControllerContext controllerContext)
    {
        base.Initialize(controllerContext);
    }

    protected User ActiveUser
    {
        get
        {
            var request = ControllerContext.Request;
            if (request.Headers.Authorization != null && request.Headers.Authorization.Scheme.Equals("bearer", StringComparison.OrdinalIgnoreCase))
            {
                return Helpers.JwtAuthentication.UserToken(request.Headers.Authorization.Parameter);
            }
            return null;
        }
    }
}

额外建议:使用HttpContext.Items存储请求级数据

如果需要在请求的多个环节共享用户信息,还可以将解析后的用户对象存入HttpContext.Items,这是请求级别的存储容器,天然和当前请求绑定,不会出现线程安全问题:

protected override void Initialize(HttpControllerContext controllerContext)
{
    base.Initialize(controllerContext);

    var request = controllerContext.Request;
    if (request.Headers.Authorization != null && request.Headers.Authorization.Scheme.Equals("bearer", StringComparison.OrdinalIgnoreCase))
    {
        var user = Helpers.JwtAuthentication.UserToken(request.Headers.Authorization.Parameter);
        controllerContext.Request.Properties["CurrentUser"] = user;
    }
}

protected User ActiveUser
{
    get
    {
        ControllerContext.Request.Properties.TryGetValue("CurrentUser", out var user);
        return user as User;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 18:32:47