调用 HubConnection.Start: 状态代码: 401, 原因短语: "传入主体为 null"



我在WebApi应用程序中使用SignalR,这很好:客户端使用WebSocket传输连接到集线器,用户通过一些自定义中间件身份验证进行身份验证。

我正试图从另一个后端应用程序(.NET客户端)连接到这个集线器,为此,我建立了一个集线器连接并创建了一个hub代理,然后调用hub方法:

string auth = "someEncryptedValue"
HubConnection hubConn = new HubConnection("myUrl");
hubConn.Headers.Add("myauthtoken", auth);
IHubProxy proxy = hubConn.CreateHubProxy("hubName");
Task t = Task.Run(() => hubConn.Start(new LongPollingTransport()));
t.WaitAndUnwrap // An extension method
hubProxy.Invoke("SendMessage", message);

调用t.WaitAndUnwrap()时抛出异常(扩展方法不是问题所在)。在添加http头标记(当然,它实际上不是文本字符串"someEncryptedValue")之前,我遇到了这个传入的主体为null的问题。所以我在这里添加了它,然后在我的另一个应用程序中为集线器添加了一个自定义授权类:

public class HeadersAuthAttribute : AuthorizeAttribute
{
public override bool AuthroizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
{
string auth = request.Headers["myauthtoken"];
if (auth == "someEncryptedValue") //again, this is actually more complex than shown here
{
return true;
}
else
{
// Need to check if the incoming principal is authenticated in case
// the connection to the hub is being made the normal way through the
// WebApi instead of the proxy using http headers
return request.User?.Identity?.IsAuthenticated ?? false;
}
return false;
}
}

当然,我的集线器有headers属性:

[HeadersAuth]
public class MyHub : Hub
{
// Hub logic
}

然而,运行此操作后,我仍然得到传入的主体为null错误。然后我读到您不能将自定义http头与WebSockets一起使用,这就是为什么我将new LongPollingTransport()放在上面的hubConn.Start调用中。但这似乎并没有改变任何事情,至少没有改变我犯的错误。

有人知道会发生什么吗?如果我能用实际的集线器和授权调试代码,这样我就可以看到hubConn.Start调用时发生了什么,那就太好了。有没有一种方法可以检查http头是否正确设置和提取?如果错误是关于传入主体为null,那么身份验证是否就是问题所在?它可能是代码中试图查找用户的另一部分吗?我不知道该怎么办,因为这个集线器连接是从.NET客户端建立的。此外,我知道HeadersAuthAttribute类正在被调用,并且在正常使用WebSockets连接到集线器时使用正确,因为它进入了检查IIdentity是否经过身份验证的其他情况。

只是想添加更多我尝试过的内容:

  • 我故意将身份验证字符串标记设为错误,以查看是否出现其他错误,但我仍然得到传入主体为null。

  • 我意识到,我的集线器的OnConnected()覆盖方法调用了一个方法,该方法尝试使用this.Context.User的传入主体,而不检查它是否为null。我删除了它和其他任何试图在集线器中使用传入主体的东西,但不幸的是,它仍然给出了相同的错误。

我发现了问题所在。这与集线器身份验证无关,正如我在完成这篇文章时所怀疑的那样。发生的情况是,我的启动文件调用app.ConfigureAuth,但这最终导致在OWIN中间件管道中进行一些自定义授权,以检查传入主体是否为null。我已经为SignalR连接删除了它。

还应该注意的是,在我开始工作后,我无法从代理进行集线器方法调用,因为它没有被授权这样做

public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)

HeadersAuthAttribute课程,我从这里得到的。

最新更新