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
相关产品推荐
相关产品推荐

