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

SignalR Core 无法与Cookie认证协同工作问题求助

解决SignalR Core与Cookie认证协同工作的问题

看起来你遇到的核心问题是SignalR Hub无法获取已认证的用户身份——虽然HTTP请求的认证流程正常,但Hub连接建立后身份信息就丢失了。结合你的代码,我整理了几个关键修复点:


1. 不要用IHttpContextAccessor获取Hub的用户身份

SignalR的连接在握手阶段(HTTP请求)完成后,后续的Hub方法调用是基于WebSocket的持久连接,不再经过完整的HTTP管道。IHttpContextAccessor只能获取当前HTTP请求的上下文,而Hub本身提供了Context.User属性,专门用于获取当前连接的用户身份。修改你的TestHub:

public class TestHub: Hub
{
    public override async Task OnConnectedAsync()
    {
        // 直接使用Hub自带的Context.User,而非IHttpContextAccessor
        bool isAuthenticated = Context.User.Identity.IsAuthenticated;
        await Task.FromResult(1);
    }

    [Authorize]
    public Task SendAuth(string message)
    {
        return Clients.All.InvokeAsync("SendAuth", message + " Authed");
    }

    // ...其他方法
}

2. 修正认证中间件的配置和顺序

你的Startup里AddAuthentication()没有指定默认认证方案,虽然AddIdentity会自动添加Cookie认证,但明确配置默认方案能避免SignalR识别认证方式时出错:

在ConfigureServices中修改:

// 替换原来的services.AddAuthentication();
services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
});

另外,自定义中间件的位置建议调整到UseAuthentication之后——你的中间件是在_next(context)之后检查用户身份,放在认证之后能确保你看到的是经过认证后的上下文:

在Configure中调整顺序:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

// 先执行认证中间件
app.UseAuthentication();
// 再执行自定义中间件
app.UseMiddleware<MyMiddleware>();
// 最后挂载SignalR
app.UseSignalR(routes =>
{
    routes.MapHub<TestHub>("TestHub");
});

app.UseMvc(routes =>
{
    routes.MapRoute(name: "default", template: "{controller=App}/{action=Index}/{id?}");
});

3. 确保WebSocket请求正确传递Cookie

客户端使用HttpClientHandler的CookieContainer是正确的,但要确认HubConnection在建立WebSocket连接时确实携带了认证Cookie。如果你的客户端和服务器存在跨域(哪怕是端口不同),还需要配置CORS允许携带凭证:

在ConfigureServices中添加CORS配置:

services.AddCors(options =>
{
    options.AddPolicy("SignalRCors", builder =>
    {
        builder.WithOrigins("http://localhost:5000") // 替换成你的客户端实际地址
               .AllowAnyMethod()
               .AllowAnyHeader()
               .AllowCredentials(); // 关键:允许携带Cookie等凭证
    });
});

然后在Configure中启用CORS(要放在UseAuthentication之后,UseSignalR之前):

app.UseCors("SignalRCors");

4. 明确SignalR Hub的认证方案(可选)

如果上面的步骤仍未解决问题,可以在映射Hub时明确指定认证方案,强制SignalR使用Cookie认证:

app.UseSignalR(routes =>
{
    routes.MapHub<TestHub>("TestHub").RequireAuthorization(options =>
    {
        options.AuthenticationSchemes = new[] { CookieAuthenticationDefaults.AuthenticationScheme };
    });
});

按照这些步骤修改后,Hub应该就能正确获取已认证的用户身份,调用[Authorize]标记的方法也不会再出现授权失败的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:08:29