调用HubConnection.Start时抛出错误:StatusCode:401,ReasonPhrase:'传入的主体为空'

时间:2017-01-20 03:16:24

标签: c# signalr

我正在将SignalR与我的WebApi应用程序一起使用,并且工作正常:客户端使用WebSocket传输连接到集线器,并且用户通过一些自定义中间件身份验证进行身份验证。

我正在尝试从另一个后端应用程序(.NET客户端)连接到此集线器并执行此操作我创建集线器连接并创建集线器代理,然后调用集线器方法:

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")。所以我在这里添加了,然后我在我的其他应用程序中为集线器添加了一个自定义授权类:

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;
    }
}

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

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

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

有谁知道会发生什么?如果我可以使用实际的集线器和授权来调试代码,那么我会很高兴,因此我可以看到hubConn.Start调用时发生了什么。有没有办法可以检查http标头设置是否正确并正确获取?如果错误是关于传入的主体为空,那么验证甚至是问题吗?它可能是代码的另一部分,它试图找到用户吗?我不知道该怎么办,因为这个集线器连接是从.NET客户端完成的。另外,我知道正在调用HeadersAuthAttribute类,并且在使用WebSockets连接到集线器时正确使用它,因为它进入了检查IIdentity已经过身份验证的其他情况。

只是添加一些我尝试过的内容:

  • 我故意让auth字符串令牌错误,看我是否得到了不同的错误,但我仍然得到传入的主体是空的。

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

1 个答案:

答案 0 :(得分:0)

我弄清楚出了什么问题。这与集线器身份验证没有关系,因为我怀疑我正在完成这篇文章。发生的事情是我的启动文件调用app.ConfigureAuth,但最终导致OWIN中间件管道中的一些自定义授权,检查传入的主体是否为空。我已经把它用于SignalR连接。

还应该注意的是,在我开始工作之后,我无法从代理进行集线器方法调用,因为它没有被授权这样做。为了解决这个问题,我添加了

public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)

到我here获得的HeadersAuthAttribute课程。