6

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

在 MVC 控制器中有两种方法提供对聊天视图的访问:
1. 第一种方法是公共的,允许匿名用户聊天 - 没有授权。2.对于域用户 - 聊天代理,
使用属性限制对第二种方法的访问。 Hub 中没有明确指定的授权。 对于这种情况,我在 IIS 上涉及 Windows 和匿名身份验证。 我还实现了自定义角色提供程序,它仅在内存中运行 - 不会将任何内容持久化到数据库中。[Authorize]




发生的情况是,在控制器方法中使用“[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&connectionToken=dYOwFxa1mkgdpzw-jitRpWq9oxRlrTet8U_dAzWjFQEdGNJfVXeG7Op0NZZwvznxeNdJCuPT75CKzQqI9HRPThV3uEDt-Z2qtIl9E02gF481&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&tid=9

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


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

有人可以对此有所了解吗?

提前致谢 :)

4

2 回答 2

9

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

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

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

泰勒的回答是正确的。当您的客户发生变化时,您应该stop然后您的 SignalR 连接。这将强制执行一个新请求,该请求将为您的客户端提供一个新的连接 id,并使用您的客户端的 updated 签名。startIdentitynegotiateconnectionTokenIdentity

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

于 2013-03-19T18:40:44.967 回答
3

你说的都是真的,它实际上发生在我的问题中。

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

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

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

这种情况导致您描述的情况 -connect以不同的方式调用,Identity集线器send返回The connection id is in the incorrect format.

于 2013-03-20T20:41:04.643 回答