ASP.NET Core Angular项目如何获取SignalR连接的IdentityServer4登录用户
解决步骤
- Angular端SignalR连接配置修正
WebSocket协议无法自定义请求头,所以SignalR客户端需要将JWT令牌放在查询参数中传输,配置连接时使用accessTokenFactory传入你的IdentityServer4颁发的访问令牌:
import { HubConnectionBuilder } from '@microsoft/signalr'; // 示例代码,token从你的Identity存储逻辑中获取 const token = yourAuthService.getAccessToken(); this.hubConnection = new HubConnectionBuilder() .withUrl('https://你的后端地址/你的hub路径', { accessTokenFactory: () => token }) .build();
- 后端JWT认证逻辑适配SignalR
默认JWT认证中间件只会从Authorization请求头读取令牌,你需要配置中间件从查询参数中读取SignalR请求的令牌,注意配置顺序必须放在AddAuthentication和AddJwtBearer之后:
using Microsoft.AspNetCore.Authentication.JwtBearer; services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { // 这里放你原本的IdentityServer4 JWT配置,比如Authority、Audience等 options.Authority = "你的IdentityServer4地址"; options.Audience = "你的API资源名称"; }); // 新增配置,处理SignalR的令牌读取 services.PostConfigure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options => { options.Events ??= new JwtBearerEvents(); options.Events.OnMessageReceived = context => { var accessToken = context.Request.Query["access_token"]; var requestPath = context.HttpContext.Request.Path; // 只处理对应Hub路径的请求 if (!string.IsNullOrEmpty(accessToken) && requestPath.StartsWithSegments("/你的hub路径")) { context.Token = accessToken; } return Task.CompletedTask; }; });
- IUserIdProvider实现与注册
首先要避免Claim映射问题,ASP.NET Core默认会将JWT中的sub声明映射为ClaimTypes.NameIdentifier,如果映射未生效可以直接读取sub声明,同时必须将自定义的IUserIdProvider注册到依赖注入容器:
// 自定义IUserIdProvider实现 public class CustomUserIdProvider : IUserIdProvider { public string GetUserId(HubConnectionContext connection) { return connection.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? connection.User?.FindFirst("sub")?.Value; } } // 在Program.cs/Startup.cs中注册 services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
- Hub添加认证特性
必须在你的Hub类上添加[Authorize]特性,才会触发认证逻辑填充User对象:
[Authorize] public class YourHub : Hub { // 你的Hub逻辑 public override async Task OnConnectedAsync() { // 此时Context.User已经有身份信息 var userId = Context.UserIdentifier; // 直接获取IUserIdProvider返回的用户ID await base.OnConnectedAsync(); } }
完成以上配置后,你就可以直接使用hub.Clients.User(userId).SendAsync(...)向指定用户定向推送消息。
内容的提问来源于stack exchange,提问作者Boppity Bop
相关产品推荐
相关产品推荐

