2013-03-19 97 views
6

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


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

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

我还实现了自定义角色提供程序,它仅在内存中运行 - 不会将任何内容持久存储到数据库中。SignalR - 使用Windows和匿名身份验证时,连接ID的格式不正确

会发生什么事是,使用“[授权]”在控制器方法属性导致从集线器responsing 500,既当呼叫从授权的视图来了,匿名之一:

请求(send是中枢方法发送消息):

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/> 

但注意,当连接到集线器工作正常,返回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

我发现很少similiar线程这里计算器:
signalr The connection id is in the incorrect format


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

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

感谢提前:)

回答

9

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请求,该请求将为您的客户端提供一个新的连接标识,其中新的connectionToken已与客户更新的Identity签署。

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

+0

感谢澄清。 – mskuza 2013-03-20 07:45:00

+0

但我发现的棘手的部分是''connect''和'send'在授权后执行 - 用户调用由'[Authorize]装饰的控制器方法'在调用Hub时发生什么事情 - 因此当调用'connect'时从Javascript,用户已被授权。我的理解是在执行MVC操作期间,在任何对Hub的调用之前,“Identity”都会被更改。 – mskuza 2013-03-20 08:01:37

+0

看看你的堆栈跟踪,很清楚你的用户的'Identity'在'negotiate'和'send'请求之间改变了。这可能是通过AJAX请求或会话超时发生的。 – halter73 2013-03-20 18:11:35

3

这就是你所说的话,它实际上发生在我的问题。

但我也发现,根本原因:
一个设计过程中主要的假设是允许匿名用户使用聊天而无需登录和后端的用户(代理)登录到使用其Windows凭据限制聊天区域。

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

以上配置实际发生的是:
1.当客户端(代理)请求限制视图(让我们说这是/Chat/Agent)的[Authorize]属性将初始化身份验证(Windows)
2.客户端JavaScript请求Negotiate,什么产生connectionId并与客户端的Windows绑定它Identity
3.这里是棘手的部分:由于集线器不使用任何身份验证明确,调用send方法不会导致任何认证请求 - IIS匿名身份验证需要precedency Windows身份验证之前,和send请求发送匿名Identity - 但在Hub实际connectionId有关Identity在2点

通过此方案会导致您所描述的情况 - connect被称为具有不同Identitysend和集线器返回The connection id is in the incorrect format.