调用 HubConnection.Start 时抛出错误:StatusCode:401,ReasonPhrase:'Incoming principal is null'
Error thrown when calling HubConnection.Start: StatusCode: 401, ReasonPhrase: 'Incoming principal is null'
我将 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 header 标记(当然,它实际上不是文字字符串 "someEncryptedValue")之前,我遇到了这个 incoming principal is null 问题。所以我在这里添加了它,然后我在我的其他应用程序中为集线器添加了自定义授权 class:
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
}
但是,在 运行 这之后我仍然得到传入主体为空错误。然后我读到您不能将自定义 http headers 与 WebSockets 一起使用,这就是为什么我将 new LongPollingTransport()
放在上面的 hubConn.Start
调用中的原因。但这似乎并没有改变任何东西,至少没有改变我得到的错误。
有人知道会发生什么吗?如果我可以使用实际的集线器和授权调试代码,那就太好了,这样我就可以在进行 hubConn.Start
调用时看到发生了什么。有没有一种方法可以检查 http header 是否设置正确并正确获取?如果错误是关于传入的主体为空,那么身份验证甚至是问题所在吗?它可能是它试图找到用户的代码的另一部分吗?我不确定该怎么做,因为这个集线器连接是从 .NET 客户端建立的。此外,我知道 HeadersAuthAttribute
class 正在被调用,并且在正常使用 WebSockets 连接到集线器时被正确使用,因为它进入了检查 IIdentity
是否已通过身份验证的其他情况。
只是添加更多我尝试过的内容:
我故意将 auth string token 弄错了,看看我是否得到了不同的错误,但我仍然得到 incoming principal is null。
我意识到我的集线器的 OnConnected()
覆盖方法调用了一种方法,该方法尝试将传入主体与 this.Context.User
一起使用,而不检查它是否为空。我删除了它和任何其他试图在集线器中使用传入主体的东西,但不幸的是它仍然给出同样的错误。
我知道出了什么问题。这与集线器身份验证无关,正如我在完成此 post 时所怀疑的那样。发生的事情是我的启动文件进行了调用 app.ConfigureAuth
,但这最终导致 OWIN 中间件管道中的一些自定义授权检查传入主体是否为空。我已将其取出用于 SignalR 连接。
还应该注意的是,在我开始工作之后,我无法从代理进行集线器方法调用,因为它没有被授权这样做。为了解决这个问题,我添加了
public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
到 HeadersAuthAttribute
class,这是我从 here 得到的。
我将 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 header 标记(当然,它实际上不是文字字符串 "someEncryptedValue")之前,我遇到了这个 incoming principal is null 问题。所以我在这里添加了它,然后我在我的其他应用程序中为集线器添加了自定义授权 class:
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
}
但是,在 运行 这之后我仍然得到传入主体为空错误。然后我读到您不能将自定义 http headers 与 WebSockets 一起使用,这就是为什么我将 new LongPollingTransport()
放在上面的 hubConn.Start
调用中的原因。但这似乎并没有改变任何东西,至少没有改变我得到的错误。
有人知道会发生什么吗?如果我可以使用实际的集线器和授权调试代码,那就太好了,这样我就可以在进行 hubConn.Start
调用时看到发生了什么。有没有一种方法可以检查 http header 是否设置正确并正确获取?如果错误是关于传入的主体为空,那么身份验证甚至是问题所在吗?它可能是它试图找到用户的代码的另一部分吗?我不确定该怎么做,因为这个集线器连接是从 .NET 客户端建立的。此外,我知道 HeadersAuthAttribute
class 正在被调用,并且在正常使用 WebSockets 连接到集线器时被正确使用,因为它进入了检查 IIdentity
是否已通过身份验证的其他情况。
只是添加更多我尝试过的内容:
我故意将 auth string token 弄错了,看看我是否得到了不同的错误,但我仍然得到 incoming principal is null。
我意识到我的集线器的
OnConnected()
覆盖方法调用了一种方法,该方法尝试将传入主体与this.Context.User
一起使用,而不检查它是否为空。我删除了它和任何其他试图在集线器中使用传入主体的东西,但不幸的是它仍然给出同样的错误。
我知道出了什么问题。这与集线器身份验证无关,正如我在完成此 post 时所怀疑的那样。发生的事情是我的启动文件进行了调用 app.ConfigureAuth
,但这最终导致 OWIN 中间件管道中的一些自定义授权检查传入主体是否为空。我已将其取出用于 SignalR 连接。
还应该注意的是,在我开始工作之后,我无法从代理进行集线器方法调用,因为它没有被授权这样做。为了解决这个问题,我添加了
public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
到 HeadersAuthAttribute
class,这是我从 here 得到的。