提问人:RETOVSKEJ 提问时间:11/12/2023 更新时间:11/12/2023 访问量:39
SignalR 无法访问 HUB 内部的上下文
SignalR no access to Context inside of the HUB
问:
我正在构建通知系统,我有一个问题,这导致我已经损失了几个小时。我的 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()
答:
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)]
评论
.withUrl(
, instead of `.withUrl(`/TicketSocket