【问题标题】:SignalR - The connection id is in the incorrect format when using Windows and Anonymous authenticationSignalR - 使用 Windows 和匿名身份验证时,连接 ID 的格式不正确
【发布时间】:2013-03-19 13:57:10
【问题描述】:

我使用 SignalR 1.0.1 作为 ASP.NET MVC3 应用程序的聊天核心。使用 IIS 7.5

MVC 控制器中有两种方法提供对聊天视图的访问:
1.第一种方法是公开的,允许匿名用户聊天-没有授权。
2. 对于域用户 - 聊天代理,使用 [Authorize] 属性限制对第二种方法的访问。

Hub 中没有明确指定的授权。
对于这种情况,我在 IIS 上同时涉及 Windows 和匿名身份验证。

我还实现了自定义角色提供程序,它仅在内存中运行 - 不会将任何内容持久化到数据库中。

发生的情况是,在控制器方法中使用“[Authorize]”属性会导致 Hub 响应 500,无论是来自授权视图的调用还是匿名视图:

请求(send是发送消息的Hub方法):

http://localhost:8101/signalr/send?transport=serverSentEvents&connectionToken=VIXEZzWQSn5SNlA8RUy4iaOPDFdvuPBjMvFBiG2FLfvfxF347XHwtapsEV5ndU4OEI0Xb64W2ZRXTqwBiL2CXg2_JlTaTJ2RnVOj4bjvx6tQaYhAqTaXs9k2853GYqzd0

回复:

The connection id is in the incorrect format.

Server stack trace:
   at Microsoft.AspNet.SignalR.PersistentConnection.GetConnectionId(HostContext context, String connectionToken)
   at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(HostContext context)
   at Microsoft.AspNet.SignalR.Owin.CallHandler.Invoke(IDictionary2 environment)
   at Microsoft.AspNet.SignalR.Owin.Handlers.HubDispatcherHandler.Invoke(IDictionary2 environment)
   at Microsoft.Owin.Host.SystemWeb.OwinCallContext.Execute()
   at Microsoft.Owin.Host.SystemWeb.OwinHttpHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object extraData)<br/><br/>

但请注意,连接到 Hub 工作正常,返回 200 OK:
http://localhost:8101/signalr/connect?transport=serverSentEvents&amp;connectionToken=dYOwFxa1mkgdpzw-jitRpWq9oxRlrTet8U_dAzWjFQEdGNJfVXeG7Op0NZZwvznxeNdJCuPT75CKzQqI9HRPThV3uEDt-Z2qtIl9E02gF481&amp;connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&amp;tid=9

我在 stackoverflow 上发现了类似的线程:
signalr The connection id is in the incorrect format


据我了解,在调用我的Send 方法时,集线器正在处理Identity 的请求,这与用于连接集线器的请求不同,或者集线器的GetConnectionId 发现,该用户实际上未被授权 - 但它是如何检查该假设,当集线器本身没有指定授权时?

有人可以解释一下吗?

提前致谢:)

【问题讨论】:

    标签: asp.net-mvc authentication connection signalr


    【解决方案1】:

    SignalR 将您的连接 ID 和 Identity 一起签名,以便在您每次启动新连接时创建一个新的 connectionToken。这个connectionToken 然后作为negotiate 响应的一部分发送到SignalR 客户端。

    每次您向 SignalR 发出请求时,无论是 connectreconnect 还是 send 请求,SignalR 都会验证您的 connectionToken 是否与您客户端的连接 ID 和 Identity 匹配。

    connectionToken 本质上是一个 CSRF 令牌,用于防止运行第三方网站的攻击者代表共享客户端秘密发出 SignalR 请求。显然,如果您启用了 SignalR 的跨域支持,这将无济于事,但 connectionToken 在这种情况下仍然可以正常工作。

    Taylor's answer 是正确的。当您的客户的Identity 更改时,您应该先stop 然后start 您的 SignalR 连接。这将强制发出一个新的 negotiate 请求,该请求将为您的客户端提供一个新的连接 ID,其中包含一个新的 connectionToken,并使用您的客户端更新后的 Identity 签名。

    附:服务器发送的事件connect 请求没有失败,因为它是在您的客户端的Identity 更改之前建立的。 connectionToken 仅在收到请求时检查,但服务器发送的事件会无限期地保持响应打开。

    【讨论】:

    • 但我发现的棘手部分是 connectsend 在授权后执行 - 用户调用控制器方法装饰有 [Authorize] 这为他提供了调用 Hub 发生的视图 - 所以当从 Javascript 调用 connect 时,用户已经被授权。我的理解是 Identity 在任何调用 Hub 之前更改 - 在 MVC 操作执行期间。
    • 查看您的堆栈跟踪,很明显您的用户的Identitynegotiatesend 请求之间发生了变化。这可能是通过 AJAX 请求或会话超时发生的。
    • 我有同样的情况,我可以让调用者从服务器端断开,在我的代码中登录帐户控制器方法。如果 ValidateUser ok 我想断开调用者,所以他必须再次连接到枢纽。我该怎么做?
    • 我在通过 iOS 客户端调用 SignalR Hub 时遇到了同样的问题。我的流程如下: 1. 用户登录调用使用 WebSecurity.Login 方法的登录服务 2. 登录服务返回成功。 3.打开hub连接调用Test hub方法(登录前不打开连接)。 4. 我收到上述错误。任何帮助将不胜感激。
    【解决方案2】:

    你说的都是真的,而且确实发生在我的问题中。

    但我也找到了根本原因:
    设计期间的主要假设之一是允许匿名用户无需登录即可使用聊天,并允许后端用户(代理)使用其 Windows 凭据登录到受限聊天区域。

    因此,在 IIS 管理器上,我启用了匿名身份验证(允许匿名用户使用聊天)和 Windows 身份验证(允许代理使用其 Windows 凭据进行访问)。
    MVC 应用程序配置为使用 Windows 身份验证 - 问题中提到的 [Authorize] 属性,但仅用于限制代理查看聊天的访问权限。

    上述配置实际发生的情况是:
    1.当客户端(代理)请求受限视图(假设它是/Chat/Agent)时,[Authorize] 属性初始化身份验证(Windows)
    2.客户端Javascript请求Negotiate,生成connectionId并绑定到客户端的WindowsIdentity
    3.这里是棘手的部分:因为Hub没有显式使用任何身份验证,调用send方法不会导致任何身份验证请求-IIS匿名身份验证优先于Windows身份验证,send请求与匿名Identity一起发送- 但在 Hub 中,实际 connectionId 与第 2 点中传递的 Identity 有关。

    这种情况会导致您描述的情况 - connect 被调用时使用与 send 不同的 Identity 并且 Hub 返回 The connection id is in the incorrect format.

    【讨论】:

      猜你喜欢
      • 2019-09-27
      • 1970-01-01
      • 1970-01-01
      • 2020-12-21
      • 1970-01-01
      • 1970-01-01
      • 2011-05-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多