.NET SignalR同时配置Cookie认证时JWT Bearer认证失效问题求解
问题根因
SignalR 客户端在使用 WebSocket、ServerSentEvents 等传输协议时,无法自定义请求头,因此AccessTokenProvider提供的令牌默认会放到请求的access_token查询参数中,而默认 JWT 认证中间件只会从Authorization请求头读取令牌,导致你的OnMessageReceived事件在 SignalR 场景下未检测到有效令牌,没有触发 JWT 认证流程,最终授权失败。
解决方案
步骤1:补全 JWT Bearer 配置的OnMessageReceived事件逻辑
在现有 JWT 配置中新增查询参数令牌的读取逻辑,针对 SignalR Hub 路径做特殊处理:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Login"; options.ExpireTimeSpan = TimeSpan.FromMinutes(12); options.SlidingExpiration = true; }) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, opt => { // 原有配置保留 // ... opt.Events = new JwtBearerEvents { OnMessageReceived = context => { // 读取查询参数中的access_token var accessToken = context.Request.Query["access_token"]; // 仅针对你的SignalR Hub路径处理,避免影响其他接口 var requestPath = context.HttpContext.Request.Path; if (!string.IsNullOrEmpty(accessToken) && requestPath.StartsWithSegments("/你的Hub实际映射路径")) // 比如"/hubs/serviceHub" { // 将查询参数中的令牌赋值给上下文,触发后续JWT认证 context.Token = accessToken; } // 原有OnMessageReceived逻辑保留 // ... return Task.CompletedTask; } }; });
步骤2:确认 Hub 端点映射配置
检查 Startup/Program 中的端点映射,确保 Hub 的路径和上一步判断的路径一致:
app.UseEndpoints(endpoints => { // 替换为你实际的Hub类和路径 endpoints.MapHub<ServiceHub>("/你的Hub实际映射路径"); // 其他原有端点配置保留 });
可选优化
可以直接在 Hub 类上标注授权特性,统一管控该 Hub 下所有方法的权限,无需每个方法单独加:
[Authorize(Policy = "SignalRService")] public class ServiceHub : Hub { public async Task RegisterService(string clientIdString) { /*...*/ } }
该方案无需修改默认认证方案,原有 Cookie 认证体系完全不受影响,同时 SignalR 场景的 JWT 认证可以正常触发。
内容的提问来源于stack exchange,提问作者Lightbringer
相关产品推荐
相关产品推荐

