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

.NET Core 3.0 SignalR连接时UserIdentifier及User.Identity.Name为null

问题分析与解决方案

你遇到的Context.User.Identity.Name和UserIdentifier为null的问题,核心原因是你的.NET Core服务端没有配置身份认证中间件。SignalR本身不负责用户身份的识别,它依赖于.NET Core的认证系统来获取用户信息——如果没有配置认证,服务端就无法识别当前连接的用户,自然这些属性都是null。

下面是具体的解决步骤:

1. 配置服务端身份认证

首先需要在你的.NET Core 3.0项目中添加并启用身份认证中间件,根据你的客户端类型(Angular是SPA,推荐用JWT;如果是传统Web可以用Cookie)选择合适的认证方式:

方式一:Cookie认证(适合简单场景)

在Startup.cs的ConfigureServices方法中添加:

using Microsoft.AspNetCore.Authentication.Cookies;

public void ConfigureServices(IServiceCollection services)
{
    // 其他服务配置...
    
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(options =>
        {
            options.LoginPath = "/Account/Login"; // 替换为你的登录页面路径
        });
    
    services.AddSignalR();
}

然后在Configure方法中,必须保证中间件顺序正确——UseAuthentication要放在UseRouting之后,UseEndpoints之前:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // 其他中间件(比如UseStaticFiles、UseHttpsRedirection)...
    
    app.UseRouting();

    // 启用认证和授权
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<MessageHub>("/message"); // 映射SignalR Hub
        // 其他路由配置...
    });
}

方式二:JWT认证(适合Angular这类SPA)

如果你的Angular客户端用JWT做身份验证,需要在服务端配置JWT支持:
在Startup.cs的ConfigureServices中添加:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

public void ConfigureServices(IServiceCollection services)
{
    // 其他服务配置...
    
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = Configuration["Jwt:Issuer"], // 从appsettings.json读取配置
                ValidAudience = Configuration["Jwt:Audience"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
            };

            // 为SignalR配置JWT解析:从查询字符串或请求头获取token
            options.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =>
                {
                    var accessToken = context.Request.Query["access_token"];
                    var path = context.HttpContext.Request.Path;
                    // 当请求SignalR Hub时,从查询字符串获取token
                    if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/message"))
                    {
                        context.Token = accessToken;
                    }
                    return Task.CompletedTask;
                }
            };
        });
    
    services.AddSignalR();
}

对应的Angular客户端连接时,需要带上JWT token:

// 从本地存储获取已登录用户的JWT token
const jwtToken = localStorage.getItem('auth_token');

public startConnection = () => {
    this.hubConnection = new signalR.HubConnectionBuilder()
        .withUrl('https://localhost:44363/message',{ 
            skipNegotiation: true, 
            transport: signalR.HttpTransportType.WebSockets,
            accessTokenFactory: () => jwtToken // 传递token到服务端
        })
        .build();
    // 后续连接逻辑...
}

2. 自定义UserIdentifier(可选)

Context.UserIdentifier默认等于Context.User.Identity.Name,如果你想用用户ID或其他标识作为UserIdentifier,可以自定义IUserIdProvider:

  1. 创建自定义Provider类:
using Microsoft.AspNetCore.SignalR;
using System.Security.Claims;

public class CustomUserIdProvider : IUserIdProvider
{
    public string GetUserId(HubConnectionContext connection)
    {
        // 这里返回用户的唯一标识,比如从Claim中获取用户ID
        return connection.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
    }
}
  1. 在Startup.cs的ConfigureServices中注册这个服务:
services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();

3. 验证身份是否生效

你可以在MessageHub的OnConnectedAsync方法中添加日志,确认用户是否已认证:

public override Task OnConnectedAsync()
{
    Console.WriteLine($"用户是否已认证: {Context.User.Identity.IsAuthenticated}");
    if (Context.User.Identity.IsAuthenticated)
    {
        string name = Context.User.Identity.Name;
        MyUsers.TryAdd(Context.ConnectionId, name);
        Console.WriteLine($"已添加用户: {name},连接ID: {Context.ConnectionId}");
    }
    return base.OnConnectedAsync();
}

4. 修正私有消息发送逻辑

当用户身份正确后,Clients.Users(user)就能正确定位到目标用户了——这里的user参数需要是目标用户的UserIdentifier(或Identity.Name,取决于你的配置)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 14:57:40