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

SignalR通知微服务:如何传递用户身份信息

解决SignalR微服务关联用户身份的方案

以下是几种可行的实现方式,根据你的场景选择:

1. 基于JWT令牌的身份传递(推荐生产环境使用)

让客户端在连接SignalR Hub时携带JWT令牌,同时在SignalR微服务中配置JWT认证,这样Context.User就能正确获取用户身份。

服务端配置(Program.cs)

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

var builder = WebApplication.CreateBuilder(args);

// 添加JWT认证
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            // 配置成和你的API一致的颁发者、受众、密钥
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };

        // 处理SignalR的令牌传递(SignalR会把令牌放在查询参数里)
        options.Events = new JwtBearerEvents
        {
            OnMessageReceived = context =>
            {
                var accessToken = context.Request.Query["access_token"];
                var hubPath = context.HttpContext.Request.Path;
                
                if (!string.IsNullOrEmpty(accessToken) && hubPath.StartsWithSegments("/hubs/你的Hub名称"))
                {
                    context.Token = accessToken;
                }
                return Task.CompletedTask;
            }
        };
    });

builder.Services.AddAuthorization();
builder.Services.AddSignalR();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapHub<你的Hub类>("/hubs/你的Hub名称");

app.Run();

客户端连接时携带令牌(Blazor示例)

// 获取当前用户的JWT令牌(比如从本地存储或AuthState获取)
var token = await GetUserJwtToken();

var hubConnection = new HubConnectionBuilder()
    .WithUrl("https://你的SignalR服务地址/hubs/你的Hub名称", options =>
    {
        options.AccessTokenProvider = () => Task.FromResult(token);
    })
    .Build();

await hubConnection.StartAsync();

配置完成后,你的OnConnectedAsync方法就能正常获取Context.User.Identity.Name,无需修改原有逻辑。

2. 通过查询参数传递身份(快速验证或非敏感场景)

如果不想引入JWT认证,可以在连接时通过查询参数传递用户名/用户ID,服务端从HttpContext中读取:

客户端连接示例

var userName = "当前登录用户名";
var hubConnection = new HubConnectionBuilder()
    .WithUrl($"https://你的SignalR服务地址/hubs/你的Hub名称?userName={Uri.EscapeDataString(userName)}")
    .Build();

await hubConnection.StartAsync();

服务端修改OnConnectedAsync

private readonly static ConcurrentDictionary<string, string> _connectionMap = new();

public override Task OnConnectedAsync()
{
    var connectionId = Context.ConnectionId;
    var httpContext = Context.GetHttpContext();
    var userName = httpContext?.Request.Query["userName"].ToString();

    if (!string.IsNullOrEmpty(userName))
    {
        _connectionMap.TryAdd(connectionId, userName);
    }

    return base.OnConnectedAsync();
}

注意:这种方式没有加密,必须配合HTTPS使用,且不适合传递敏感信息,生产环境建议优先用JWT方案。

3. API中转关联身份

如果是API向SignalR推送通知,也可以由API在调用SignalR时传递用户身份与ConnectionId的关联关系:

  • API在收到客户端请求时,同时获取用户身份和对应的SignalR ConnectionId
  • 调用SignalR微服务的自定义方法(比如RegisterUserConnection),将用户名和ConnectionId绑定
  • SignalR服务端维护这个映射关系,后续推送时根据用户名找到对应的ConnectionId

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 10:42:32