SignalR 无法访问 HUB 内部的上下文

SignalR no access to Context inside of the HUB

提问人:RETOVSKEJ 提问时间:11/12/2023 更新时间:11/12/2023 访问量:39

问:

我正在构建通知系统,我有一个问题,这导致我已经损失了几个小时。我的 JWT 身份验证与前端完美配合,但是在向后端发送(完全相同的)JWT 令牌时,我永远无法访问 Context / Context.User 等。我的意思是,我获得了访问权限,但用户,基本上一切都是空的或空的。

我尝试了 [AllowAnonymous] [Authorize]、使用方案授权、不使用、在整个集线器上授权、仅在 OnConnectedAsync 上授权等的所有组合。

如果我手动解析令牌,在 ConnectedAsync 中像这样,一切正常:

var token = Context.GetHttpContext().Request.Query["access_token"];
var userIdString = GetUserIdFromToken(token);
public class TicketHub : Hub
{
    private readonly ITicketsRepository _ticketRepository;
    public TicketHub(ITicketsRepository ticketRepository)
    {
        _ticketRepository = ticketRepository;
    }

    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme, Policy = "IsAuthenticated")]
    public override async Task OnConnectedAsync()
    {
      var test = Context.User.Identity.IsAuthenticated;
      var test2 = Context; // ->>>> NO CONTEXT HERE

我的程序.cs:(大部分跳过,仅包括中间件和身份验证模式的顺序)

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwt =>
{
    var key = Encoding.ASCII.GetBytes(Configuration["JwtConfig:Secret"]);
    jwt.SaveToken = true;
    jwt.TokenValidationParameters = tokenValidationParams;
    jwt.Events = new JwtBearerEvents
    {
        OnMessageReceived = context =>
        {
            var accessToken = context.Request.Query["access_token"];

            var path = context.HttpContext.Request.Path;
            if (!string.IsNullOrEmpty(accessToken) &&
                path.StartsWithSegments("/TicketSocket"))
            {
                context.Token = accessToken; 
            }
            return Task.CompletedTask;
        }
    };
}
);

builder.Services.AddSignalR();
var app = builder.Build();
app.UseRouting();
app.UseWebSockets();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapHub<TicketHub>("/TicketSocket");
}

我的前端:

this.connection = new HubConnectionBuilder()
        .withUrl(`api/TicketSocket`, {
          accessTokenFactory: () => this.$auth.strategy.token.get(),
        })
        .withAutomaticReconnect()
        .build()
.NET ASP.Net-Core WebSocket JWT 信号器

评论

0赞 Jason Pan 11/13/2023
为什么在前端连接集线器时使用 api/TicketSocket。.withUrl(, instead of `.withUrl(`/TicketSocket

答:

0赞 davidfowl 11/12/2023 #1

将 Authorize 属性放在 OnConnectedAsync 上是无效的。您需要将其放在 TicketHub 上。

评论

0赞 RETOVSKEJ 11/12/2023
正如我所说,我尝试了此属性的许多组合。在这里,我刚刚粘贴了上次尝试的那个。 在 TicketHub 上方,导致 401 在版本协商上未经授权。localhost:4029/api/TicketSocket/negotiate?negotiateVersion=1[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]