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

使用WebSocket时AbpSession.UserId始终为null的原因排查

问题:ASP.NET Boilerplate中WebSocket连接时AbpSession.UserId始终为null的原因

我正在使用ASP.NET Boilerplate框架,尝试在用户建立WebSocket连接时将连接与登录用户ID关联,但发现AbpSession.UserId的值始终为null,而该值在其他类中可正常获取。相关代码与配置如下:

服务端代码

public class WebSocketServerConnectionManager : ITransientDependency
{
    private ConcurrentDictionary<string, WebSocket> _socket = new ConcurrentDictionary<string, WebSocket>();

    public IAbpSession AbpSession { get; set; }

    public WebSocketServerConnectionManager()
    {
        AbpSession = NullAbpSession.Instance;
    }

    public ConcurrentDictionary<string, WebSocket> GetAllSockets()
    {
        return _socket;
    }

    public string AddSocket(WebSocket socket) 
    {
        try
        {
            var ConnId = AbpSession.UserId.ToString(); //<==== Null
            // Guid.NewGuid().ToString();
            //var test = AbpSession.UserId;
            _socket.TryAdd(ConnId/*dictionary item key*/, socket/*dictionary item value*/);
            Debug.WriteLine("Connection Added:" + ConnId);
            return ConnId;
        }
        catch(Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }
}

客户端WebSocket初始化代码

async ngOnInit() {
    this.connectWebSocket();
}

connectWebSocket(){
    this.socket=new WebSocket(this.webSocketUrl);
    this.socket.onopen=(event)=>{};
    this.socket.onclose=(event)=>{};
    this.socket.onmessage=(event)=>{
        this.isConnID(event.data);
    };
}

AuthConfigurer中的代码

/* This method is needed to authorize SignalR javascript client.
 * SignalR can not send authorization header. So, we are getting it from query string as an encrypted text. */
private static Task QueryStringTokenResolver(MessageReceivedContext context)
{
    var test = context.HttpContext.Request.Path.Value;//the value is null
    if (!context.HttpContext.Request.Path.HasValue ||
        (!context.HttpContext.Request.Path.Value.StartsWith("/signalr") && !context.HttpContext.Request.Path.Value.StartsWith("/ws")))
    {
        // We are just looking for signalr clients
        return Task.CompletedTask;
    }

    var qsAuthToken = context.HttpContext.Request.Query["enc_auth_token"].FirstOrDefault();
    if (qsAuthToken == null)
    {
        // Cookie value does not matches to querystring value
        return Task.CompletedTask;
    }

    // Set auth token from cookie
    context.Token = SimpleStringCipher.Instance.Decrypt(qsAuthToken, AppConsts.DefaultPassPhrase);
    return Task.CompletedTask;
}

appsettings.json的Authentication配置

"Authentication": {
    "JwtBearer": {
        "IsEnabled": "true",
        "SecurityKey": "Test_C421AAEE0D114E9C",
        "Issuer": "Test",
        "Audience": "Test"
    }
},

原因分析

  • WebSocket连接未携带认证Token
    客户端初始化WebSocket时,this.webSocketUrl没有附加enc_auth_token参数。服务端的QueryStringTokenResolver依赖该参数获取加密的JWT Token,缺少这个参数就无法完成认证,自然无法通过AbpSession获取用户ID。

  • 认证路径匹配逻辑失效
    代码中context.HttpContext.Request.Path.Value为null,导致路径判断条件!context.HttpContext.Request.Path.HasValue成立,直接跳过了Token解析逻辑。即使WebSocket路径是/ws或/signalr,也不会执行认证流程,无法建立用户会话。

  • WebSocket处理管道未集成ABP会话上下文
    WebSocket连接的处理流程可能没有经过ABP的核心中间件(如UseAbp()),导致AbpSession无法从当前请求上下文获取已认证的用户信息。ABP的会话依赖请求上下文的认证结果,如果WebSocket管道未正确集成ABP中间件,AbpSession会默认使用NullAbpSession.Instance,返回null。

  • AbpSession注入时机问题
    虽然WebSocketServerConnectionManager实现了ITransientDependency,但如果WebSocket连接的处理是在ABP请求上下文之外进行的(比如直接在底层WebSocket中间件中调用),AbpSession可能没有被正确注入当前用户的会话信息,依然使用默认的NullAbpSession。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 19:39:45